Skip to content

Commit

Permalink
Fix inconsistent handling of mixed nullable contexts
Browse files Browse the repository at this point in the history
Allow using non-null returning mapping methods when target type does allow nulls
  • Loading branch information
latonz committed Oct 24, 2024
1 parent 5e237ac commit 4eca202
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 1 deletion.
4 changes: 3 additions & 1 deletion src/Riok.Mapperly/Descriptors/MappingBuilderContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,9 @@ bool ignoreDerivedTypes
Location? diagnosticLocation = null
)
{
return FindMapping(mappingKey) ?? BuildMapping(mappingKey, options, diagnosticLocation);
return FindMapping(mappingKey)
?? FindMapping(mappingKey.TargetNonNullable())
?? BuildMapping(mappingKey, options, diagnosticLocation);
}

/// <summary>
Expand Down
2 changes: 2 additions & 0 deletions src/Riok.Mapperly/Descriptors/TypeMappingKey.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ public TypeMappingKey(ITypeMapping mapping, TypeMappingConfiguration? config = n

public TypeMappingKey NonNullable() => new(Source.NonNullable(), Target.NonNullable(), Configuration);

public TypeMappingKey TargetNonNullable() => new(Source, Target.NonNullable(), Configuration);

public override bool Equals(object? obj) =>
obj is TypeMappingKey other
&& _comparer.Equals(Source, other.Source)
Expand Down
29 changes: 29 additions & 0 deletions test/Riok.Mapperly.Tests/Mapping/ObjectPropertyNullableTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -899,4 +899,33 @@ private A(C value)
"""
);
}

[Fact]
public Task MixedNullableContextsWithDerivedTypesShouldWork()
{
var source = TestSourceBuilder.MapperWithBodyAndTypes(
"""
[MapDerivedType<A, B>]
public partial BBase Map(ABase src);
""",
"""
#nullable disable
public abstract record BBase
{
public List<BBase> Objects { get; init; } = [];
}
public record B : BBase;
#nullable enable
public abstract record ABase
{
public List<ABase> Objects { get; init; } = [];
}
public record A: ABase;
"""
);
return TestHelper.VerifyGenerator(source);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
//HintName: Mapper.g.cs
// <auto-generated />
#nullable enable
public partial class Mapper
{
[global::System.CodeDom.Compiler.GeneratedCode("Riok.Mapperly", "0.0.1.0")]
public partial global::BBase Map(global::ABase src)
{
return src switch
{
global::A x => MapToB(x),
_ => throw new System.ArgumentException($"Cannot map {src.GetType()} to BBase as there is no known derived type mapping", nameof(src)),
};
}

[global::System.CodeDom.Compiler.GeneratedCode("Riok.Mapperly", "0.0.1.0")]
private global::B MapToB(global::A source)
{
var target = new global::B()
{
Objects = MapToListOfBBase(source.Objects),
};
return target;
}

[global::System.CodeDom.Compiler.GeneratedCode("Riok.Mapperly", "0.0.1.0")]
private global::System.Collections.Generic.List<global::BBase?> MapToListOfBBase(global::System.Collections.Generic.IReadOnlyCollection<global::ABase> source)
{
var target = new global::System.Collections.Generic.List<global::BBase?>(source.Count);
foreach (var item in source)
{
target.Add(Map(item));
}
return target;
}
}

0 comments on commit 4eca202

Please sign in to comment.