Skip to content

Commit

Permalink
fix: initialize nullable members for nested containers (#1660)
Browse files Browse the repository at this point in the history
---------

Co-authored-by: latonz <[email protected]>
  • Loading branch information
clegoz and latonz authored Jan 20, 2025
1 parent e7420df commit d397ef2
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public class MembersContainerBuilderContext<T>(MappingBuilderContext builderCont
where T : IMemberAssignmentTypeMapping
{
private readonly Dictionary<MemberPath, MemberNullDelegateAssignmentMapping> _nullDelegateMappings = new();
private readonly HashSet<MemberPath> _initializedNullableTargetPaths = [];
private readonly HashSet<(IMemberAssignmentMappingContainer, MemberPath)> _initializedNullableTargetPaths = [];

public void AddMemberAssignmentMapping(IMemberAssignmentMapping memberMapping) => AddMemberAssignmentMapping(Mapping, memberMapping);

Expand Down Expand Up @@ -79,7 +79,7 @@ private void AddMemberAssignmentMapping(IMemberAssignmentMappingContainer contai
// the target should be non-null after this assignment and can be set as initialized.
if (!mapping.MemberInfo.IsSourceNullable && mapping.MemberInfo.TargetMember.MemberType.IsNullable())
{
_initializedNullableTargetPaths.Add(mapping.MemberInfo.TargetMember);
_initializedNullableTargetPaths.Add((container, mapping.MemberInfo.TargetMember));
}
}

Expand All @@ -93,7 +93,10 @@ private void AddNullMemberInitializers(IMemberAssignmentMappingContainer contain
if (!nullablePath.Member.CanSet)
continue;

if (!_initializedNullableTargetPaths.Add(nullablePath))
if (_initializedNullableTargetPaths.Contains((Mapping, nullablePath)))
continue;

if (!_initializedNullableTargetPaths.Add((container, nullablePath)))
continue;

if (!BuilderContext.InstanceConstructors.TryBuild(BuilderContext.Source, type, out var ctor))
Expand Down
75 changes: 75 additions & 0 deletions test/Riok.Mapperly.Tests/Mapping/ObjectPropertyNullableTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -588,6 +588,81 @@ public partial B Map(A a)
);
}

[Fact]
public void NullableNestedMembersShouldInitializeWithNoNullAssignment()
{
var source = TestSourceBuilder.MapperWithBodyAndTypes(
"""
[MapProperty("NullableValue1", "V.NullableValue1")]
[MapProperty("NullableValue2", "V.NullableValue2")]
public partial B Map(A a)
""",
TestSourceBuilderOptions.Default with
{
AllowNullPropertyAssignment = false,
},
"class A { public int? NullableValue1 { get; set; } public int? NullableValue2 { get; set; } }",
"class B { public C? V { get; set; } }",
"class C { public int? NullableValue1 { get; set; } public int? NullableValue2 { get; set; } }"
);

TestHelper
.GenerateMapper(source)
.Should()
.HaveMapMethodBody(
"""
var target = new global::B();
if (a.NullableValue1 != null)
{
target.V ??= new global::C();
target.V.NullableValue1 = a.NullableValue1.Value;
}
if (a.NullableValue2 != null)
{
target.V ??= new global::C();
target.V.NullableValue2 = a.NullableValue2.Value;
}
return target;
"""
);
}

[Fact]
public void NullableNestedMembersShouldInitializeWithNoNullAssignmentOutsideContainer()
{
var source = TestSourceBuilder.MapperWithBodyAndTypes(
"""
[MapProperty("NullableValue1", "V.NullableValue1")]
[MapProperty("Value2", "V.Value2")]
public partial B Map(A a)
""",
TestSourceBuilderOptions.Default with
{
AllowNullPropertyAssignment = false,
},
"class A { public int? NullableValue1 { get; set; } public int Value2 { get; set; } }",
"class B { public C? V { get; set; } }",
"class C { public int? NullableValue1 { get; set; } public int? Value2 { get; set; } }"
);

TestHelper
.GenerateMapper(source)
.Should()
.HaveMapMethodBody(
"""
var target = new global::B();
if (a.NullableValue1 != null)
{
target.V ??= new global::C();
target.V.NullableValue1 = a.NullableValue1.Value;
}
target.V ??= new global::C();
target.V.Value2 = a.Value2;
return target;
"""
);
}

[Fact]
public void NullableClassToNullableClassPropertyThrowShouldSetNull()
{
Expand Down

0 comments on commit d397ef2

Please sign in to comment.