Skip to content

Commit

Permalink
handle nullable value types with MapValueAttribute and methods correct
Browse files Browse the repository at this point in the history
  • Loading branch information
latonz committed Oct 15, 2024
1 parent c2fc50a commit a61f006
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -181,10 +181,10 @@ private static bool ValidateValueProviderMethod(IMembersBuilderContext<IMapping>
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)
Expand Down
59 changes: 57 additions & 2 deletions test/Riok.Mapperly.Tests/Mapping/ObjectPropertyValueMethodTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ public void MethodReturnTypeMismatchShouldDiagnostic()
}

[Fact]
public void MethodReturnTypeNullMismatchShouldDiagnostic()
public void MethodReturnTypeNullableToNonNullableShouldDiagnostic()
{
var source = TestSourceBuilder.MapperWithBodyAndTypes(
"""
Expand Down Expand Up @@ -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()
{
Expand All @@ -197,7 +222,7 @@ public void MethodReturnValueTypeNonNullableToNullable()
""",
"class A;",
"class B { public C? Value { get; set; } }",
"enum C { C1 };"
"enum C { C1 }"
);

TestHelper
Expand All @@ -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<C> 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()
{
Expand Down

0 comments on commit a61f006

Please sign in to comment.