Skip to content

Commit

Permalink
fix: initialize nullable values when assigning null to a child member
Browse files Browse the repository at this point in the history
  • Loading branch information
latonz committed Aug 8, 2024
1 parent 0870816 commit 6649fb8
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,23 @@ public void AddNullDelegateMemberAssignmentMapping(IMemberAssignmentMapping memb
return;
}

// set target member to null if null assignments are allowed
// and the source is null
var setMemberToNull =
BuilderContext.Configuration.Mapper.AllowNullPropertyAssignment
&& memberMapping.MemberInfo.TargetMember.Member.Type.IsNullable();

// if the member is explicitly set to null,
// make sure the parent members are initialized/non-null,
// no matter of the null conditional source-path.
// otherwise this initialization would only happen
// if the source member is not null,
// and the null assignment in the else case could fail if the target parent member is not initialized.
if (setMemberToNull)
{
AddNullMemberInitializers(Mapping, memberMapping.MemberInfo.TargetMember);
}

var nullConditionSourcePath = new NonEmptyMemberPath(
memberMapping.MemberInfo.SourceMember.MemberPath.RootType,
memberMapping.MemberInfo.SourceMember.MemberPath.PathWithoutTrailingNonNullable().ToList()
Expand All @@ -41,10 +58,7 @@ public void AddNullDelegateMemberAssignmentMapping(IMemberAssignmentMapping memb

// set target member to null if null assignments are allowed
// and the source is null
if (
BuilderContext.Configuration.Mapper.AllowNullPropertyAssignment
&& memberMapping.MemberInfo.TargetMember.Member.Type.IsNullable()
)
if (setMemberToNull)
{
var targetMemberSetter = memberMapping.MemberInfo.TargetMember.BuildSetter(BuilderContext);
container.AddNullMemberAssignment(targetMemberSetter);
Expand Down
35 changes: 35 additions & 0 deletions test/Riok.Mapperly.Tests/Mapping/ObjectPropertyNullableTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -518,6 +518,41 @@ TestSourceBuilderOptions.Default with
);
}

[Fact]
public void NullableNestedMembersShouldInitialize()
{
var source = TestSourceBuilder.MapperWithBodyAndTypes(
"""
[MapProperty("Value", "SubValue.Value")]
public partial B Map(A a)
""",
"class A { public C? Value { get; set; } }",
"class B { public D? SubValue { get; set; } }",
"class C { public int V { get; set; } }",
"class D { public E? Value { get; set; } }",
"class E { public int V { get; set; } }"
);

TestHelper
.GenerateMapper(source)
.Should()
.HaveMapMethodBody(
"""
var target = new global::B();
target.SubValue ??= new global::D();
if (a.Value != null)
{
target.SubValue.Value = MapToE(a.Value);
}
else
{
target.SubValue.Value = null;
}
return target;
"""
);
}

[Fact]
public void NullableClassToNullableClassPropertyThrowShouldSetNull()
{
Expand Down

0 comments on commit 6649fb8

Please sign in to comment.