Closed onionhammer closed 1 year ago
Thanks for the bug report, I'll look into it.
Here's a repro:
[Mapper(PropertyNameMappingStrategy = PropertyNameMappingStrategy.CaseInsensitive)]
public class MapperClass
{
public static partial Car MapCar(CarDto input);
public static partial CarDto MapCar(Car input);
}
public record CarDto()
{
public JsonElement? Amendment { get; set; }
}
public record Car()
{
[JsonIgnore, System.Runtime.Serialization.IgnoreDataMember]
public OtherThing? AmendmentMetadata
{
get => Amendment?.Deserialize<OtherThing>(JsonExtensions.JsonOptions);
}
[JsonIgnore, System.Runtime.Serialization.DataMember]
public string? AmendmentValue
{
get => Amendment?.GetRawText();
set => Amendment = value != null ? JsonSerializer.Deserialize<JsonElement>(value) : null;
}
[JsonInclude, System.Runtime.Serialization.IgnoreDataMember]
public JsonElement? Amendment { get; set; }
}
public class OtherThing
{
public string? Value { get; set; }
}
Away rn, but I'm guessing because Amendment
is a Nullable<JsonElement>
, mapperly sees an object with a Value
field and attempts to map it? Because mapperly automatically accesses the Value
field (because it knows its not null), it then attempts to now "access" the value member, and fails because it has already been accessed.
@TimothyMakkison I think its because of the Value
suffix and some special case with Mapperly for nullables?
If you rename AmendmentValue
to AmendmentVal
it compiles.
@TimothyMakkison I think its because of the
Value
suffix and some special case with Mapperly for nullables?If you rename
AmendmentValue
toAmendmentVal
it compiles.
Yeah I've updated my comment with more speculation. I'm guessing it only affects nullable value types because its an actual type. Does this not happen with V2?
@TimothyMakkison maybe it was just doing a throw new NotImplementedException
on v2
It's strange this issue didn't crop up when field mapping was introduced. Iirc one of my nit pick optimizations changed how nullable types were checked, perhaps that broke it. #555
One bug which I just found but also existed in v2.8.0 is that a nested nullable struct's flattened values cannot be resolved. I created another issue https://github.com/riok/mapperly/issues/572 since I'm not sure if it is related to this issue.
I don't think #555 caused it I've been using the following
[Fact]
public void VaueTest()
{
var source = TestSourceBuilder.MapperWithBodyAndTypes(
"partial B Map(A src);",
"public record A(int? P);",
"public record B { public int PValue { get; set; } }"
);
TestHelper
.GenerateMapper(source)
.Should()
.HaveSingleMethodBody(
"""
var target = new global::B();
if (src.P != null)
{
target.PValue = src.P.Value.Value;
}
return target;
"""
);
}
@TimothyMakkison The test you provided, which should reproduce the bug described by OP, fails on v2.8.0. So this probably exists since a longer time and isn't a regression of v2.9.0-next.3
The test passes when the bug occurs. Does this mean the bug doesn't happen with 2.8?
@TimothyMakkison sorry my bad, I adjusted the test to verify that the bug does not exist. If I use exact your version, it fails on v2.8.0
as well as on v2.9.0-next.3
.
The problem is that the target property has a auto-flattened name of ending with Value
. When resolving the name, autoflattening resolves it to P.Value
(the value property of Nullable<T>
). Then when building the mapping, the builder encounters a nullable value type and adds another .Value
to access the value inside the null if condition. It relates to https://github.com/riok/mapperly/issues/572. If Nullable<T>
properties are treated as T
while resolving mappable members, the problem shouldn't occur.
Name of this issue makes no sense anymore, should we close as duplicate?
I adjusted the title. I think this is a slightly different issue than https://github.com/riok/mapperly/issues/572. Here the name of the target property Value
which matches the Value
property of Nullable<T>
, which is special cased, is a problem. While in #572 the problem is that the member resolution does take Nullable<T>
into account, while the user certainly expects T
. However, the solution could probably be the same.
Describe the bug I upgraded from next-2 to next-3 and now I am receiving a build error
It looks like the generated code is calling
.Value
twice: