From 719be05957ada932699d91d8cba11d14fbc7cbaa Mon Sep 17 00:00:00 2001 From: Mattias Nordqvist Date: Sun, 10 Nov 2024 02:06:05 +0100 Subject: [PATCH] working on sourcegenertor --- .../CreateMapperAttribute.g.cs | 3 +- ...FartingUnicorn.Benchmarks.UserProfile.g.cs | 140 +++++++++++++++++- FartingUnicorn.Benchmarks/Program.cs | 2 +- .../CreateMapperAttribute.g.cs | 3 +- ...NonNullableNonOptional_Tests.BlogPost.g.cs | 44 +++++- ...pe.NonNullableOptional_Tests.BlogPost.g.cs | 49 ++++++ ...eType.NullableOptional_Tests.BlogPost.g.cs | 49 ++++++ FartingUnicorn.Tests/SingleField.cs | 80 ++++++---- FartingUnicorn/Mapper.cs | 14 +- MapperGenerator/MapperGenerator.cs | 116 +++++++++++---- MapperGenerator/SourceBuilder.cs | 28 ++-- .../CreateMapperAttribute.g.cs | 3 +- ...WeatherForecastController.UserProfile.g.cs | 140 +++++++++++++++++- 13 files changed, 577 insertions(+), 94 deletions(-) create mode 100644 FartingUnicorn.Tests/Generated/MapperGenerator/MapperGenerator.MapperGenerator/Mapper.FartingUnicorn.Tests.SingleField.ReferenceType.NonNullableOptional_Tests.BlogPost.g.cs create mode 100644 FartingUnicorn.Tests/Generated/MapperGenerator/MapperGenerator.MapperGenerator/Mapper.FartingUnicorn.Tests.SingleField.ReferenceType.NullableOptional_Tests.BlogPost.g.cs diff --git a/FartingUnicorn.Benchmarks/Generated/MapperGenerator/MapperGenerator.MapperGenerator/CreateMapperAttribute.g.cs b/FartingUnicorn.Benchmarks/Generated/MapperGenerator/MapperGenerator.MapperGenerator/CreateMapperAttribute.g.cs index bcef4eb..688fbeb 100644 --- a/FartingUnicorn.Benchmarks/Generated/MapperGenerator/MapperGenerator.MapperGenerator/CreateMapperAttribute.g.cs +++ b/FartingUnicorn.Benchmarks/Generated/MapperGenerator/MapperGenerator.MapperGenerator/CreateMapperAttribute.g.cs @@ -1,5 +1,4 @@ - -namespace DotNetThoughts.FartingUnicorn +namespace DotNetThoughts.FartingUnicorn { [System.AttributeUsage(System.AttributeTargets.Class)] public class CreateMapperAttribute : System.Attribute diff --git a/FartingUnicorn.Benchmarks/Generated/MapperGenerator/MapperGenerator.MapperGenerator/Mapper.FartingUnicorn.Benchmarks.UserProfile.g.cs b/FartingUnicorn.Benchmarks/Generated/MapperGenerator/MapperGenerator.MapperGenerator/Mapper.FartingUnicorn.Benchmarks.UserProfile.g.cs index c54e817..ff01219 100644 --- a/FartingUnicorn.Benchmarks/Generated/MapperGenerator/MapperGenerator.MapperGenerator/Mapper.FartingUnicorn.Benchmarks.UserProfile.g.cs +++ b/FartingUnicorn.Benchmarks/Generated/MapperGenerator/MapperGenerator.MapperGenerator/Mapper.FartingUnicorn.Benchmarks.UserProfile.g.cs @@ -2,11 +2,145 @@ using System.Text.Json; namespace FartingUnicorn.Generated; + public static partial class Mappers { - public static Result MapToUserProfile(JsonElement jsonElement) + public static Result MapToFartingUnicorn_Benchmarks_UserProfile(JsonElement jsonElement, string[] path = null) { - var result = new FartingUnicorn.Benchmarks.UserProfile(); - return Result.Ok(result); + /*object*/ + { + if (jsonElement.ValueKind != JsonValueKind.Object) + { + return Result.Error(new ValueHasWrongTypeError(path, "Object", jsonElement.ValueKind.ToString())); + } + } + var obj = new FartingUnicorn.Benchmarks.UserProfile(); + + Result compositeResult = UnitResult.Ok; + var isNamePropertyDefined = jsonElement.TryGetProperty("Name", out var jsonNameProperty); + if (isNamePropertyDefined) + { + // String + var mapResult = MapString(jsonNameProperty, /*mapperOptions,*/ [.. path, Name]); + if (mapResult.Success) + { + obj.Name = mapResult.Value; + } + else + { + compositeResult = compositeResult.Or(mapResult); + } + } + else + { + } + var isAgePropertyDefined = jsonElement.TryGetProperty("Age", out var jsonAgeProperty); + if (isAgePropertyDefined) + { + // Int32 + if (mapResult.Success) + { + obj.Age = mapResult.Value; + } + else + { + compositeResult = compositeResult.Or(mapResult); + } + } + else + { + } + var isIsSubscribedPropertyDefined = jsonElement.TryGetProperty("IsSubscribed", out var jsonIsSubscribedProperty); + if (isIsSubscribedPropertyDefined) + { + // Boolean + if (mapResult.Success) + { + obj.IsSubscribed = mapResult.Value; + } + else + { + compositeResult = compositeResult.Or(mapResult); + } + } + else + { + } + var isCoursesPropertyDefined = jsonElement.TryGetProperty("Courses", out var jsonCoursesProperty); + if (isCoursesPropertyDefined) + { + // + if (mapResult.Success) + { + obj.Courses = mapResult.Value; + } + else + { + compositeResult = compositeResult.Or(mapResult); + } + } + else + { + } + var isPetPropertyDefined = jsonElement.TryGetProperty("Pet", out var jsonPetProperty); + if (isPetPropertyDefined) + { + // Pet + if (mapResult.Success) + { + obj.Pet = mapResult.Value; + } + else + { + compositeResult = compositeResult.Or(mapResult); + } + } + else + { + } + var isIsGayPropertyDefined = jsonElement.TryGetProperty("IsGay", out var jsonIsGayProperty); + if (isIsGayPropertyDefined) + { + // Nullable + if (mapResult.Success) + { + obj.IsGay = mapResult.Value; + } + else + { + compositeResult = compositeResult.Or(mapResult); + } + } + else + { + } + var isFavoritePetPropertyDefined = jsonElement.TryGetProperty("FavoritePet", out var jsonFavoritePetProperty); + if (isFavoritePetPropertyDefined) + { + // Pet + if (mapResult.Success) + { + obj.FavoritePet = mapResult.Value; + } + else + { + compositeResult = compositeResult.Or(mapResult); + } + } + else + { + } + if(!compositeResult.Success) + { + return Result.Error(compositeResult.Errors); + } + if(false)/*check if is option*/ + { + } + else + { + return Result.Ok(obj); + } + throw new NotImplementedException(); } } diff --git a/FartingUnicorn.Benchmarks/Program.cs b/FartingUnicorn.Benchmarks/Program.cs index 1d3a6bd..bb6d99d 100644 --- a/FartingUnicorn.Benchmarks/Program.cs +++ b/FartingUnicorn.Benchmarks/Program.cs @@ -75,6 +75,6 @@ public async Task FartingGeneratedDeserialization() { _jsonStream.Seek(0, SeekOrigin.Begin); using var json = await JsonDocument.ParseAsync(_jsonStream); - return FartingUnicorn.Generated.Mappers.MapToUserProfile(json.RootElement).ValueOrThrow(); + return FartingUnicorn.Generated.Mappers.MapToFartingUnicorn_Benchmarks_UserProfile(json.RootElement).ValueOrThrow(); } } diff --git a/FartingUnicorn.Tests/Generated/MapperGenerator/MapperGenerator.MapperGenerator/CreateMapperAttribute.g.cs b/FartingUnicorn.Tests/Generated/MapperGenerator/MapperGenerator.MapperGenerator/CreateMapperAttribute.g.cs index bcef4eb..688fbeb 100644 --- a/FartingUnicorn.Tests/Generated/MapperGenerator/MapperGenerator.MapperGenerator/CreateMapperAttribute.g.cs +++ b/FartingUnicorn.Tests/Generated/MapperGenerator/MapperGenerator.MapperGenerator/CreateMapperAttribute.g.cs @@ -1,5 +1,4 @@ - -namespace DotNetThoughts.FartingUnicorn +namespace DotNetThoughts.FartingUnicorn { [System.AttributeUsage(System.AttributeTargets.Class)] public class CreateMapperAttribute : System.Attribute diff --git a/FartingUnicorn.Tests/Generated/MapperGenerator/MapperGenerator.MapperGenerator/Mapper.FartingUnicorn.Tests.SingleField.ReferenceType.NonNullableNonOptional_Tests.BlogPost.g.cs b/FartingUnicorn.Tests/Generated/MapperGenerator/MapperGenerator.MapperGenerator/Mapper.FartingUnicorn.Tests.SingleField.ReferenceType.NonNullableNonOptional_Tests.BlogPost.g.cs index f05fff3..33d1423 100644 --- a/FartingUnicorn.Tests/Generated/MapperGenerator/MapperGenerator.MapperGenerator/Mapper.FartingUnicorn.Tests.SingleField.ReferenceType.NonNullableNonOptional_Tests.BlogPost.g.cs +++ b/FartingUnicorn.Tests/Generated/MapperGenerator/MapperGenerator.MapperGenerator/Mapper.FartingUnicorn.Tests.SingleField.ReferenceType.NonNullableNonOptional_Tests.BlogPost.g.cs @@ -2,11 +2,49 @@ using System.Text.Json; namespace FartingUnicorn.Generated; + public static partial class Mappers { - public static Result MapToBlogPost(JsonElement jsonElement) + public static Result MapToFartingUnicorn_Tests_SingleField_ReferenceType_NonNullableNonOptional_Tests_BlogPost(JsonElement jsonElement, string[] path = null) { - var result = new FartingUnicorn.Tests.SingleField.ReferenceType.NonNullableNonOptional_Tests.BlogPost(); - return Result.Ok(result); + /*object*/ + { + if (jsonElement.ValueKind != JsonValueKind.Object) + { + return Result.Error(new ValueHasWrongTypeError(path, "Object", jsonElement.ValueKind.ToString())); + } + } + var obj = new FartingUnicorn.Tests.SingleField.ReferenceType.NonNullableNonOptional_Tests.BlogPost(); + + Result compositeResult = UnitResult.Ok; + var isTitlePropertyDefined = jsonElement.TryGetProperty("Title", out var jsonTitleProperty); + if (isTitlePropertyDefined) + { + // String + var mapResult = MapString(jsonTitleProperty, /*mapperOptions,*/ [.. path, Title]); + if (mapResult.Success) + { + obj.Title = mapResult.Value; + } + else + { + compositeResult = compositeResult.Or(mapResult); + } + } + else + { + } + if(!compositeResult.Success) + { + return Result.Error(compositeResult.Errors); + } + if(false)/*check if is option*/ + { + } + else + { + return Result.Ok(obj); + } + throw new NotImplementedException(); } } diff --git a/FartingUnicorn.Tests/Generated/MapperGenerator/MapperGenerator.MapperGenerator/Mapper.FartingUnicorn.Tests.SingleField.ReferenceType.NonNullableOptional_Tests.BlogPost.g.cs b/FartingUnicorn.Tests/Generated/MapperGenerator/MapperGenerator.MapperGenerator/Mapper.FartingUnicorn.Tests.SingleField.ReferenceType.NonNullableOptional_Tests.BlogPost.g.cs new file mode 100644 index 0000000..222ee77 --- /dev/null +++ b/FartingUnicorn.Tests/Generated/MapperGenerator/MapperGenerator.MapperGenerator/Mapper.FartingUnicorn.Tests.SingleField.ReferenceType.NonNullableOptional_Tests.BlogPost.g.cs @@ -0,0 +1,49 @@ +using DotNetThoughts.Results; +using System.Text.Json; + +namespace FartingUnicorn.Generated; + +public static partial class Mappers +{ + public static Result MapToFartingUnicorn_Tests_SingleField_ReferenceType_NonNullableOptional_Tests_BlogPost(JsonElement jsonElement, string[] path = null) + { + /*object*/ + { + if (jsonElement.ValueKind != JsonValueKind.Object) + { + return Result.Error(new ValueHasWrongTypeError(path, "Object", jsonElement.ValueKind.ToString())); + } + } + var obj = new FartingUnicorn.Tests.SingleField.ReferenceType.NonNullableOptional_Tests.BlogPost(); + + Result compositeResult = UnitResult.Ok; + var isTitlePropertyDefined = jsonElement.TryGetProperty("Title", out var jsonTitleProperty); + if (isTitlePropertyDefined) + { + // Option + if (mapResult.Success) + { + obj.Title = mapResult.Value; + } + else + { + compositeResult = compositeResult.Or(mapResult); + } + } + else + { + } + if(!compositeResult.Success) + { + return Result.Error(compositeResult.Errors); + } + if(false)/*check if is option*/ + { + } + else + { + return Result.Ok(obj); + } + throw new NotImplementedException(); + } +} diff --git a/FartingUnicorn.Tests/Generated/MapperGenerator/MapperGenerator.MapperGenerator/Mapper.FartingUnicorn.Tests.SingleField.ReferenceType.NullableOptional_Tests.BlogPost.g.cs b/FartingUnicorn.Tests/Generated/MapperGenerator/MapperGenerator.MapperGenerator/Mapper.FartingUnicorn.Tests.SingleField.ReferenceType.NullableOptional_Tests.BlogPost.g.cs new file mode 100644 index 0000000..ebfa0b2 --- /dev/null +++ b/FartingUnicorn.Tests/Generated/MapperGenerator/MapperGenerator.MapperGenerator/Mapper.FartingUnicorn.Tests.SingleField.ReferenceType.NullableOptional_Tests.BlogPost.g.cs @@ -0,0 +1,49 @@ +using DotNetThoughts.Results; +using System.Text.Json; + +namespace FartingUnicorn.Generated; + +public static partial class Mappers +{ + public static Result MapToFartingUnicorn_Tests_SingleField_ReferenceType_NullableOptional_Tests_BlogPost(JsonElement jsonElement, string[] path = null) + { + /*object*/ + { + if (jsonElement.ValueKind != JsonValueKind.Object) + { + return Result.Error(new ValueHasWrongTypeError(path, "Object", jsonElement.ValueKind.ToString())); + } + } + var obj = new FartingUnicorn.Tests.SingleField.ReferenceType.NullableOptional_Tests.BlogPost(); + + Result compositeResult = UnitResult.Ok; + var isTitlePropertyDefined = jsonElement.TryGetProperty("Title", out var jsonTitleProperty); + if (isTitlePropertyDefined) + { + // Option + if (mapResult.Success) + { + obj.Title = mapResult.Value; + } + else + { + compositeResult = compositeResult.Or(mapResult); + } + } + else + { + } + if(!compositeResult.Success) + { + return Result.Error(compositeResult.Errors); + } + if(false)/*check if is option*/ + { + } + else + { + return Result.Ok(obj); + } + throw new NotImplementedException(); + } +} diff --git a/FartingUnicorn.Tests/SingleField.cs b/FartingUnicorn.Tests/SingleField.cs index f9b21e1..e80b51b 100644 --- a/FartingUnicorn.Tests/SingleField.cs +++ b/FartingUnicorn.Tests/SingleField.cs @@ -8,19 +8,21 @@ using Xunit; using static FartingUnicorn.Mapper; -using FartingUnicorn.Generated; namespace FartingUnicorn.Tests; + + public class SingleField { public class ReferenceType { public class NonNullableNonOptional_Tests { - public static IEnumerable GetMappers => + public static IEnumerable GetMappers => [ [(Func>)(x => Map(x, null, null))], - [Mappers.MapToBlogPost] + [(Func>)(x => FartingUnicorn.Generated.Mappers.MapToFartingUnicorn_Tests_SingleField_ReferenceType_NonNullableNonOptional_Tests_BlogPost(x, null))] + ]; [CreateMapper] @@ -111,10 +113,10 @@ public class BlogPost public void ValidSingleField() { var jsonElement = JsonSerializer.Deserialize(""" - { - "Title": "Farting Unicorns" - } - """); + { + "Title": "Farting Unicorns" + } + """); var blogPost = Mapper.Map(jsonElement); Assert.True(blogPost.Success); @@ -158,6 +160,13 @@ public void NulledNullableField() public class NonNullableOptional_Tests { + public static IEnumerable GetMappers => + [ + [(Func>)(x => Map(x, null, null))], + [(Func>)(x => Generated.Mappers.MapToFartingUnicorn_Tests_SingleField_ReferenceType_NonNullableOptional_Tests_BlogPost(x, null))] + ]; + + [CreateMapper] public class BlogPost { /// @@ -198,15 +207,16 @@ public void MissingNonNullableField() blogPost.Errors.Single().Message.Should().Be("$.Title is required"); } - [Fact] - public void NulledOptionalField() + [Theory] + [MemberData(nameof(GetMappers))] + public void NulledOptionalField(Func> map) { var jsonElement = JsonSerializer.Deserialize(""" - { - "Title": null - } - """); - var blogPost = Mapper.Map(jsonElement); + { + "Title": null + } + """); + var blogPost = map(jsonElement); Assert.True(blogPost.Success); blogPost.Value.Title.Should().BeOfType>(); @@ -216,6 +226,12 @@ public void NulledOptionalField() public class NullableOptional_Tests { + public static IEnumerable GetMappers => + [ + [(Func>)(x => Map(x, null, null))], + [(Func>)(x => Generated.Mappers.MapToFartingUnicorn_Tests_SingleField_ReferenceType_NullableOptional_Tests_BlogPost(x, null))] + ]; + [CreateMapper] public class BlogPost { /// @@ -229,10 +245,10 @@ public class BlogPost public void ValidSingleField() { var jsonElement = JsonSerializer.Deserialize(""" - { - "Title": "Farting Unicorns" - } - """); + { + "Title": "Farting Unicorns" + } + """); var blogPost = Mapper.Map(jsonElement); Assert.True(blogPost.Success); @@ -241,28 +257,30 @@ public void ValidSingleField() Assert.Equal("Farting Unicorns", someTitle.Value); } - [Fact] - public void MissingOptionalField() + [Theory] + [MemberData(nameof(GetMappers))] + public void MissingOptionalField(Func> map) { var jsonElement = JsonSerializer.Deserialize(""" - { - } - """); - var blogPost = Mapper.Map(jsonElement); + { + } + """); + var blogPost = map(jsonElement); Assert.True(blogPost.Success); blogPost.Value.Title.Should().BeNull(); } - [Fact] - public void NulledOptionalField() + [Theory] + [MemberData(nameof(GetMappers))] + public void NulledOptionalField(Func> map) { var jsonElement = JsonSerializer.Deserialize(""" - { - "Title": null - } - """); - var blogPost = Mapper.Map(jsonElement); + { + "Title": null + } + """); + var blogPost = map(jsonElement); Assert.True(blogPost.Success); blogPost.Value.Title.Should().BeOfType>(); diff --git a/FartingUnicorn/Mapper.cs b/FartingUnicorn/Mapper.cs index 408c126..9c925d3 100644 --- a/FartingUnicorn/Mapper.cs +++ b/FartingUnicorn/Mapper.cs @@ -32,14 +32,15 @@ public bool TryGetConverter(Type type, [NotNullWhen(true)] out IConverter? conve return converter != null; } } +public abstract record FartingUnicornErrorBase(string[] Path, string Message) : ErrorBase(Message); +public record MappingError(string[] Path, string Message) : FartingUnicornErrorBase(Path, $"Failed to map {string.Join(".", Path)}: {Message}"); +public record RequiredPropertyMissingError(string[] Path) : FartingUnicornErrorBase(Path, $"{string.Join(".", Path)} is required"); +public record RequiredValueMissingError(string[] Path) : FartingUnicornErrorBase(Path, $"{string.Join(".", Path)} must have a value"); +public record ValueHasWrongTypeError(string[] Path, string ExpectedType, string ActualType) : FartingUnicornErrorBase(Path, $"Value of {string.Join(".", Path)} has the wrong type. Expected {ExpectedType}, got {ActualType}"); + public class Mapper { - public abstract record FartingUnicornErrorBase(string[] Path, string Message) : ErrorBase(Message); - public record MappingError(string[] Path, string Message) : FartingUnicornErrorBase(Path, $"Failed to map {string.Join(".", Path)}: {Message}"); - public record RequiredPropertyMissingError(string[] Path) : FartingUnicornErrorBase(Path, $"{string.Join(".", Path)} is required"); - public record RequiredValueMissingError(string[] Path) : FartingUnicornErrorBase(Path, $"{string.Join(".", Path)} must have a value"); - public record ValueHasWrongTypeError(string[] Path, string ExpectedType, string ActualType) : FartingUnicornErrorBase(Path, $"Value of {string.Join(".", Path)} has the wrong type. Expected {ExpectedType}, got {ActualType}"); - public static Result Map(JsonElement json, MapperOptions mapperOptions = null, string[] path = null) + public static Result Map(JsonElement json, MapperOptions mapperOptions = null, string[] path = null) { return MapElement(typeof(T), json, mapperOptions, path).Map(x => (T)x); } @@ -249,7 +250,6 @@ public static Result MapElement(Type t, JsonElement jsonElement, MapperO } else { - return Result.Ok(obj); } } diff --git a/MapperGenerator/MapperGenerator.cs b/MapperGenerator/MapperGenerator.cs index 74e091d..107c960 100644 --- a/MapperGenerator/MapperGenerator.cs +++ b/MapperGenerator/MapperGenerator.cs @@ -31,29 +31,79 @@ public static SourceText GenerateExtensionClass(ClassToGenerateMapperFor classTo sb.AppendLine("namespace FartingUnicorn.Generated;"); sb.AppendLine(); sb.AppendLine($"public static partial class Mappers"); - sb.AppendLine("{"); - using (var _ = sb.Indent()) + using (var _1 = sb.CodeBlock()) { - sb.AppendLine($"public static Result<{classToGenerateMapperFor.FullName}> MapTo{classToGenerateMapperFor.Name}(JsonElement jsonElement)"); - sb.AppendLine("{"); - using (var __ = sb.Indent()) + sb.AppendLine($"public static Result<{classToGenerateMapperFor.FullName}> MapTo{classToGenerateMapperFor.FullName.Replace(".", "_")}(JsonElement jsonElement, string[] path = null)"); + using (var _2 = sb.CodeBlock()) { - sb.AppendLine($"var result = new {classToGenerateMapperFor.FullName}();"); - foreach (var value in classToGenerateMapperFor.Values) + sb.AppendLine("/*object*/"); + using (var _3 = sb.CodeBlock()) { - sb.AppendLine($"result.{value} = jsonElement.GetProperty(\"{value}\").GetString();"); + sb.AppendLine("if (jsonElement.ValueKind != JsonValueKind.Object)"); + using (var _4 = sb.CodeBlock()) + { + sb.AppendLine($"return Result<{classToGenerateMapperFor.FullName}>.Error(new ValueHasWrongTypeError(path, \"Object\", jsonElement.ValueKind.ToString()));"); + } } - sb.AppendLine($"return Result<{classToGenerateMapperFor.FullName}>.Ok(result);"); + sb.AppendLine($"var obj = new {classToGenerateMapperFor.FullName}();"); + sb.AppendLine(); + sb.AppendLine("Result compositeResult = UnitResult.Ok;"); + + foreach (var p in classToGenerateMapperFor.Properties) + { + sb.AppendLine($"var is{p.Name}PropertyDefined = jsonElement.TryGetProperty(\"{p.Name}\", out var json{p.Name}Property);"); + sb.AppendLine($"if (is{p.Name}PropertyDefined)"); + using (var _3 = sb.CodeBlock()) + { + sb.AppendLine($"// {p.Type}"); + if (p.Type == "String") + { + sb.AppendLine($"var mapResult = MapString(json{p.Name}Property, /*mapperOptions,*/ [.. path, \"{p.Name}\"]);"); + } + sb.AppendLine("if (mapResult.Success)"); + using (var _4 = sb.CodeBlock()) + { + sb.AppendLine($"obj.{p.Name} = mapResult.Value;"); + } + sb.AppendLine("else"); + using (var _4 = sb.CodeBlock()) + { + sb.AppendLine("compositeResult = compositeResult.Or(mapResult);"); + } + } + sb.AppendLine("else"); + using (var _3 = sb.CodeBlock()) + { + + } + } + + sb.AppendLine("if(!compositeResult.Success)"); + using (var _3 = sb.CodeBlock()) + { + sb.AppendLine($"return Result<{classToGenerateMapperFor.FullName}>.Error(compositeResult.Errors);"); + } + + sb.AppendLine("if(false)/*check if is option*/"); + using (var _3 = sb.CodeBlock()) + { + // handle if option + } + sb.AppendLine("else"); + using (var _3 = sb.CodeBlock()) + { + sb.AppendLine($"return Result<{classToGenerateMapperFor.FullName}>.Ok(obj);"); + } + sb.AppendLine("throw new NotImplementedException();"); } - sb.AppendLine("}"); } - sb.AppendLine("}"); + return sb.ToSourceText(); } } - + public void Initialize(IncrementalGeneratorInitializationContext context) { // Add the marker attribute to the compilation @@ -129,43 +179,47 @@ static bool IsSyntaxTargetForGeneration(SyntaxNode node) string className = classSymbol.ToString(); string name = classSymbol.Name.ToString(); - // Get all the members in the enum - ImmutableArray enumMembers = classSymbol.GetMembers(); - var members = new List(enumMembers.Length); - // Get all the fields from the enum, and add their name to the list - foreach (ISymbol member in enumMembers) - { - if (member is IFieldSymbol field && field.ConstantValue is not null) - { - members.Add(member.Name); - } - } - foreach (ISymbol member in enumMembers) + + // Get all the members in the enum + ImmutableArray members = classSymbol.GetMembers(); + var properties = new List(members.Length); + + // Get all the props from the class, and add their name to the list + foreach (ISymbol member in members) { - if (member is IFieldSymbol field && field.ConstantValue is not null) + if (member is IPropertySymbol p) { - members.Add(member.Name); + properties.Add(new PropertyToGenerateMapperFor(p.Name, p.Type.Name)); } } - return new ClassToGenerateMapperFor(className, name, members); + return new ClassToGenerateMapperFor(className, name, properties); } } } - +public readonly record struct PropertyToGenerateMapperFor +{ + public readonly string Name; + public readonly string Type; + public PropertyToGenerateMapperFor(string name, string type) + { + Name = name; + Type = type; + } +} public readonly record struct ClassToGenerateMapperFor { public readonly string FullName; public readonly string Name; - public readonly EquatableArray Values; + public readonly EquatableArray Properties; - public ClassToGenerateMapperFor(string fullName, string name, List values) + public ClassToGenerateMapperFor(string fullName, string name, List properties) { FullName = fullName; Name = name; - Values = new(values.ToArray()); + Properties = new(properties.ToArray()); } } diff --git a/MapperGenerator/SourceBuilder.cs b/MapperGenerator/SourceBuilder.cs index cf99b5f..65837db 100644 --- a/MapperGenerator/SourceBuilder.cs +++ b/MapperGenerator/SourceBuilder.cs @@ -28,6 +28,18 @@ public void AppendLine(string line) } } + public IDisposable CodeBlock() + { + AppendLine("{"); + var indent = Indent(); + + return new DisposeFunc(() => + { + indent.Dispose(); + AppendLine("}"); + }); + + } public IDisposable Indent() { _indentLevel++; @@ -35,7 +47,7 @@ public IDisposable Indent() { _indentStrings.Add(new string(' ', _indentSize * _indentLevel)); } - return new Unindent(() => _indentLevel--); + return new DisposeFunc(() => _indentLevel--); } public override string? ToString() @@ -52,19 +64,17 @@ internal void AppendLine() { _stringBuilder.AppendLine(); } - - private class Unindent : IDisposable + private class DisposeFunc : IDisposable { - private Func _unindent; - - public Unindent(Func unindent) + private Action _endBlock; + public DisposeFunc(Action endBlock) { - _unindent = unindent; + _endBlock = endBlock; } - public void Dispose() { - _unindent(); + _endBlock(); } } + } \ No newline at end of file diff --git a/WebApplication1/Generated/MapperGenerator/MapperGenerator.MapperGenerator/CreateMapperAttribute.g.cs b/WebApplication1/Generated/MapperGenerator/MapperGenerator.MapperGenerator/CreateMapperAttribute.g.cs index bcef4eb..688fbeb 100644 --- a/WebApplication1/Generated/MapperGenerator/MapperGenerator.MapperGenerator/CreateMapperAttribute.g.cs +++ b/WebApplication1/Generated/MapperGenerator/MapperGenerator.MapperGenerator/CreateMapperAttribute.g.cs @@ -1,5 +1,4 @@ - -namespace DotNetThoughts.FartingUnicorn +namespace DotNetThoughts.FartingUnicorn { [System.AttributeUsage(System.AttributeTargets.Class)] public class CreateMapperAttribute : System.Attribute diff --git a/WebApplication1/Generated/MapperGenerator/MapperGenerator.MapperGenerator/Mapper.WebApplication1.Controllers.WeatherForecastController.UserProfile.g.cs b/WebApplication1/Generated/MapperGenerator/MapperGenerator.MapperGenerator/Mapper.WebApplication1.Controllers.WeatherForecastController.UserProfile.g.cs index 58bb230..081af86 100644 --- a/WebApplication1/Generated/MapperGenerator/MapperGenerator.MapperGenerator/Mapper.WebApplication1.Controllers.WeatherForecastController.UserProfile.g.cs +++ b/WebApplication1/Generated/MapperGenerator/MapperGenerator.MapperGenerator/Mapper.WebApplication1.Controllers.WeatherForecastController.UserProfile.g.cs @@ -2,11 +2,145 @@ using System.Text.Json; namespace FartingUnicorn.Generated; + public static partial class Mappers { - public static Result MapToUserProfile(JsonElement jsonElement) + public static Result MapToWebApplication1_Controllers_WeatherForecastController_UserProfile(JsonElement jsonElement, string[] path = null) { - var result = new WebApplication1.Controllers.WeatherForecastController.UserProfile(); - return Result.Ok(result); + /*object*/ + { + if (jsonElement.ValueKind != JsonValueKind.Object) + { + return Result.Error(new ValueHasWrongTypeError(path, "Object", jsonElement.ValueKind.ToString())); + } + } + var obj = new WebApplication1.Controllers.WeatherForecastController.UserProfile(); + + Result compositeResult = UnitResult.Ok; + var isNamePropertyDefined = jsonElement.TryGetProperty("Name", out var jsonNameProperty); + if (isNamePropertyDefined) + { + // String + var mapResult = MapString(jsonNameProperty, /*mapperOptions,*/ [.. path, Name]); + if (mapResult.Success) + { + obj.Name = mapResult.Value; + } + else + { + compositeResult = compositeResult.Or(mapResult); + } + } + else + { + } + var isAgePropertyDefined = jsonElement.TryGetProperty("Age", out var jsonAgeProperty); + if (isAgePropertyDefined) + { + // Int32 + if (mapResult.Success) + { + obj.Age = mapResult.Value; + } + else + { + compositeResult = compositeResult.Or(mapResult); + } + } + else + { + } + var isIsSubscribedPropertyDefined = jsonElement.TryGetProperty("IsSubscribed", out var jsonIsSubscribedProperty); + if (isIsSubscribedPropertyDefined) + { + // Boolean + if (mapResult.Success) + { + obj.IsSubscribed = mapResult.Value; + } + else + { + compositeResult = compositeResult.Or(mapResult); + } + } + else + { + } + var isCoursesPropertyDefined = jsonElement.TryGetProperty("Courses", out var jsonCoursesProperty); + if (isCoursesPropertyDefined) + { + // + if (mapResult.Success) + { + obj.Courses = mapResult.Value; + } + else + { + compositeResult = compositeResult.Or(mapResult); + } + } + else + { + } + var isPetPropertyDefined = jsonElement.TryGetProperty("Pet", out var jsonPetProperty); + if (isPetPropertyDefined) + { + // Option + if (mapResult.Success) + { + obj.Pet = mapResult.Value; + } + else + { + compositeResult = compositeResult.Or(mapResult); + } + } + else + { + } + var isIsGayPropertyDefined = jsonElement.TryGetProperty("IsGay", out var jsonIsGayProperty); + if (isIsGayPropertyDefined) + { + // Nullable + if (mapResult.Success) + { + obj.IsGay = mapResult.Value; + } + else + { + compositeResult = compositeResult.Or(mapResult); + } + } + else + { + } + var isFavoritePetPropertyDefined = jsonElement.TryGetProperty("FavoritePet", out var jsonFavoritePetProperty); + if (isFavoritePetPropertyDefined) + { + // Pet + if (mapResult.Success) + { + obj.FavoritePet = mapResult.Value; + } + else + { + compositeResult = compositeResult.Or(mapResult); + } + } + else + { + } + if(!compositeResult.Success) + { + return Result.Error(compositeResult.Errors); + } + if(false)/*check if is option*/ + { + } + else + { + return Result.Ok(obj); + } + throw new NotImplementedException(); } }