From a61f00630cb5841a05272499c90f7af83a6c73f8 Mon Sep 17 00:00:00 2001 From: latonz Date: Tue, 15 Oct 2024 18:22:02 +0200 Subject: [PATCH] handle nullable value types with MapValueAttribute and methods correct --- .../MappingBodyBuilders/SourceValueBuilder.cs | 4 +- .../Mapping/ObjectPropertyValueMethodTest.cs | 59 ++++++++++++++++++- 2 files changed, 59 insertions(+), 4 deletions(-) diff --git a/src/Riok.Mapperly/Descriptors/MappingBodyBuilders/SourceValueBuilder.cs b/src/Riok.Mapperly/Descriptors/MappingBodyBuilders/SourceValueBuilder.cs index 22b58996d9..a772106aa8 100644 --- a/src/Riok.Mapperly/Descriptors/MappingBodyBuilders/SourceValueBuilder.cs +++ b/src/Riok.Mapperly/Descriptors/MappingBodyBuilders/SourceValueBuilder.cs @@ -181,10 +181,10 @@ private static bool ValidateValueProviderMethod(IMembersBuilderContext return false; } - // use non-nullable target type to allow non-null value type assignments + // use non-nullable to allow non-null value type assignments // to nullable value types var methodCandidates = namedMethodCandidates.Where(x => - SymbolEqualityComparer.Default.Equals(x.ReturnType, memberMappingInfo.TargetMember.MemberType.NonNullable()) + SymbolEqualityComparer.Default.Equals(x.ReturnType.NonNullable(), memberMappingInfo.TargetMember.MemberType.NonNullable()) ); if (!memberMappingInfo.TargetMember.Member.IsNullable) diff --git a/test/Riok.Mapperly.Tests/Mapping/ObjectPropertyValueMethodTest.cs b/test/Riok.Mapperly.Tests/Mapping/ObjectPropertyValueMethodTest.cs index fe373091c1..cee2cad2f7 100644 --- a/test/Riok.Mapperly.Tests/Mapping/ObjectPropertyValueMethodTest.cs +++ b/test/Riok.Mapperly.Tests/Mapping/ObjectPropertyValueMethodTest.cs @@ -134,7 +134,7 @@ public void MethodReturnTypeMismatchShouldDiagnostic() } [Fact] - public void MethodReturnTypeNullMismatchShouldDiagnostic() + public void MethodReturnTypeNullableToNonNullableShouldDiagnostic() { var source = TestSourceBuilder.MapperWithBodyAndTypes( """ @@ -187,6 +187,31 @@ public void MethodReturnTypeNonNullableToNullable() ); } + [Fact] + public void MethodReturnValueTypeNullableToNullable() + { + var source = TestSourceBuilder.MapperWithBodyAndTypes( + """ + [MapValue("Value", Use = nameof(BuildC))] partial B Map(A source); + C? BuildC() => C.C1; + """, + "class A;", + "class B { public C? Value { get; set; } }", + "enum C { C1 }" + ); + + TestHelper + .GenerateMapper(source) + .Should() + .HaveSingleMethodBody( + """ + var target = new global::B(); + target.Value = BuildC(); + return target; + """ + ); + } + [Fact] public void MethodReturnValueTypeNonNullableToNullable() { @@ -197,7 +222,7 @@ public void MethodReturnValueTypeNonNullableToNullable() """, "class A;", "class B { public C? Value { get; set; } }", - "enum C { C1 };" + "enum C { C1 }" ); TestHelper @@ -212,6 +237,36 @@ public void MethodReturnValueTypeNonNullableToNullable() ); } + [Fact] + public void MethodReturnValueTypeNullableToNonNullableShouldDiagnostic() + { + var source = TestSourceBuilder.MapperWithBodyAndTypes( + """ + [MapValue("Value", Use = nameof(BuildC))] partial B Map(A source); + System.Nullable BuildC() => C.C1; + """, + "class A;", + "class B { public C Value { get; set; } }", + "enum C { C1 }" + ); + + TestHelper + .GenerateMapper(source, TestHelperOptions.AllowAndIncludeAllDiagnostics) + .Should() + .HaveDiagnostic( + DiagnosticDescriptors.MapValueMethodTypeMismatch, + "Cannot assign method return type C? of BuildC() to B.Value of type C" + ) + .HaveDiagnostic(DiagnosticDescriptors.NoMemberMappings, "No members are mapped in the object mapping from A to B") + .HaveAssertedAllDiagnostics() + .HaveSingleMethodBody( + """ + var target = new global::B(); + return target; + """ + ); + } + [Fact] public void MethodReturnTypeInDisabledNullableContext() {