Skip to content

Commit

Permalink
fix: Nullable<T>.Value is no longer treated as a member
Browse files Browse the repository at this point in the history
  • Loading branch information
TimothyMakkison committed Jul 18, 2023
1 parent 984c695 commit 8f39cb3
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 8 deletions.
4 changes: 3 additions & 1 deletion src/Riok.Mapperly/Descriptors/SymbolAccessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,9 @@ private IEnumerable<IMappableMember> FindMemberPath(ITypeSymbol type, IEnumerabl
{
foreach (var name in path)
{
if (GetMappableMembers(type, name, comparer).FirstOrDefault() is not { } member)
// get T if type is Nullable<T>, prevents Value being treated as a member
var actualType = type.NonNullableValueType() ?? type;
if (GetMappableMembers(actualType, name, comparer).FirstOrDefault() is not { } member)
break;

type = member.Type;
Expand Down
14 changes: 7 additions & 7 deletions src/Riok.Mapperly/Helpers/NullableSymbolExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,13 @@ internal static bool IsNullable(this ITypeSymbol symbol) =>

internal static bool IsNullableValueType(this ITypeSymbol symbol) => symbol.NonNullableValueType() != null;

internal static ITypeSymbol? NonNullableValueType(this ITypeSymbol symbol)
{
if (symbol.IsValueType && symbol is INamedTypeSymbol { OriginalDefinition.SpecialType: SpecialType.System_Nullable_T } namedType)
return namedType.TypeArguments[0];
return null;
}

/// <summary>
/// Whether or not the <see cref="ITypeParameterSymbol"/> is nullable.
/// </summary>
Expand All @@ -104,11 +111,4 @@ internal static bool IsNullable(this ITypeParameterSymbol typeParameter, Nullabl
}

private static bool IsNullable(this NullableAnnotation nullable) => nullable is NullableAnnotation.Annotated or NullableAnnotation.None;

private static ITypeSymbol? NonNullableValueType(this ITypeSymbol symbol)
{
if (symbol.IsValueType && symbol is INamedTypeSymbol { OriginalDefinition.SpecialType: SpecialType.System_Nullable_T } namedType)
return namedType.TypeArguments[0];
return null;
}
}
75 changes: 75 additions & 0 deletions test/Riok.Mapperly.Tests/Mapping/ObjectPropertyFlatteningTest.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
using Riok.Mapperly.Diagnostics;

namespace Riok.Mapperly.Tests.Mapping;

[UsesVerify]
Expand Down Expand Up @@ -126,6 +128,79 @@ public void AutoFlattenedMultiplePropertiesNullablePath()
);
}

[Fact]
public void AutoFlattenedPropertyNullableValueTypePath()
{
var source = TestSourceBuilder.Mapping(
"A",
"B",
"public class A { public C Id { get; set; } }",
"public class B { public int IdValue { get; set; } }",
"public class C { public int? Value { get; set; } }"
);
TestHelper
.GenerateMapper(source)
.Should()
.HaveSingleMethodBody(
"""
var target = new global::B();
if (source.Id.Value != null)
{
target.IdValue = source.Id.Value.Value;
}

return target;
"""
);
}

[Fact]
public void AutoFlattenedPropertyNullableValueTypePathShouldResolve()
{
var source = TestSourceBuilder.Mapping(
"A",
"B",
"public class A { public C? Prop { get; set; } }",
"public class B { public string PropInteger { get; set; } }",
"public struct C { public int Integer { get; set; } }"
);
TestHelper
.GenerateMapper(source)
.Should()
.HaveSingleMethodBody(
"""
var target = new global::B();
if (source.Prop != null)
{
target.PropInteger = source.Prop.Value.Integer.ToString();
}

return target;
"""
);
}

[Fact]
public void AutoFlattenedPropertyNullableValueTypePathShouldDiagnostic()
{
var source = TestSourceBuilder.Mapping(
"A",
"B",
"public record A(int? Id);",
"public record B { public int IdValue { get; set; } }"
);
TestHelper
.GenerateMapper(source, TestHelperOptions.AllowDiagnostics)
.Should()
.HaveDiagnostic(DiagnosticDescriptors.SourceMemberNotFound)
.HaveSingleMethodBody(
"""
var target = new global::B();
return target;
"""
);
}

[Fact]
public void AutoFlattenedMultiplePropertiesPathDisabledNullable()
{
Expand Down

0 comments on commit 8f39cb3

Please sign in to comment.