Skip to content

Commit

Permalink
Fix inconsistent handling of mixed nullable contexts (#1558)
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 authored Oct 24, 2024
1 parent 93f0b62 commit 027445d
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;
}
}

1 comment on commit 027445d

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Performance Alert ⚠️

Possible performance regression was detected for benchmark 'SourceGeneratorBenchmarks'.
Benchmark result of this commit is worse than the previous benchmark result exceeding threshold 3.

Benchmark suite Current: 027445d Previous: e9abaf4 Ratio
Riok.Mapperly.Benchmarks.SourceGeneratorBenchmarks.Compile 2145646.79734375 ns (± 188621.84193937102) 120741.05671574519 ns (± 1678.1529391966976) 17.77
Riok.Mapperly.Benchmarks.SourceGeneratorBenchmarks.LargeCompile 49375820.53928571 ns (± 1383372.9771022343) 1277208.939174107 ns (± 7926.104374412328) 38.66

This comment was automatically generated by workflow using github-action-benchmark.

Please sign in to comment.