Skip to content

Commit

Permalink
fix: use all modifiers for user method mapping
Browse files Browse the repository at this point in the history
  • Loading branch information
ni507 committed Sep 7, 2023
1 parent 3e60dc2 commit 2087ca4
Show file tree
Hide file tree
Showing 54 changed files with 336 additions and 140 deletions.
29 changes: 17 additions & 12 deletions src/Riok.Mapperly/Descriptors/Mappings/MethodMapping.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
using Riok.Mapperly.Symbols;
using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
using static Riok.Mapperly.Emit.Syntax.SyntaxFactoryHelper;
using Accessibility = Microsoft.CodeAnalysis.Accessibility;

namespace Riok.Mapperly.Descriptors.Mappings;

Expand All @@ -22,8 +21,16 @@ public abstract class MethodMapping : NewInstanceMapping
private const int SourceParameterIndex = 0;
private const int ReferenceHandlerParameterIndex = 1;

private readonly Accessibility _accessibility = Accessibility.Private;
private static readonly IEnumerable<SyntaxToken> _privateSyntaxToken = new[] { TrailingSpacedToken(SyntaxKind.PrivateKeyword) };

private static readonly IEnumerable<SyntaxToken> _privateStaticSyntaxToken = new[]
{
TrailingSpacedToken(SyntaxKind.PrivateKeyword),
TrailingSpacedToken(SyntaxKind.StaticKeyword),
};

private readonly ITypeSymbol _returnType;
private readonly IMethodSymbol? _partialMethodDefinition;

private string? _methodName;

Expand All @@ -44,15 +51,12 @@ ITypeSymbol targetType
{
SourceParameter = sourceParameter;
IsExtensionMethod = method.IsExtensionMethod;
IsPartial = method.IsPartialDefinition;
ReferenceHandlerParameter = referenceHandlerParameter;
_accessibility = method.DeclaredAccessibility;
_partialMethodDefinition = method;
_methodName = method.Name;
_returnType = method.ReturnType.UpgradeNullable();
}

private bool IsPartial { get; }

protected bool IsExtensionMethod { get; }

private string MethodName => _methodName ?? throw new InvalidOperationException();
Expand Down Expand Up @@ -106,13 +110,14 @@ protected virtual ParameterListSyntax BuildParameterList() =>

private IEnumerable<SyntaxToken> BuildModifiers(bool isStatic)
{
yield return Accessibility(_accessibility);

if (isStatic)
yield return TrailingSpacedToken(SyntaxKind.StaticKeyword);
// if a syntax is referenced it is the implementation part of partial method definition
// then copy all modifiers otherwise only set private and optionally static
if (_partialMethodDefinition?.DeclaringSyntaxReferences.FirstOrDefault()?.GetSyntax() is MethodDeclarationSyntax syntax)
{
return syntax.Modifiers.Select(x => TrailingSpacedToken(x.Kind()));
}

if (IsPartial)
yield return TrailingSpacedToken(SyntaxKind.PartialKeyword);
return isStatic ? _privateStaticSyntaxToken : _privateSyntaxToken;
}

private void ReserveParameterNames(UniqueNameBuilder nameBuilder, ParameterListSyntax parameters)
Expand Down
12 changes: 0 additions & 12 deletions src/Riok.Mapperly/Emit/Syntax/SyntaxFactoryHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,18 +29,6 @@ private SyntaxFactoryHelper(int indentation, string assemblyName)

public SyntaxFactoryHelper RemoveIndentation() => new(Indentation - 1, _assemblyName);

public static SyntaxToken Accessibility(Accessibility accessibility)
{
return accessibility switch
{
Microsoft.CodeAnalysis.Accessibility.Private => TrailingSpacedToken(SyntaxKind.PrivateKeyword),
Microsoft.CodeAnalysis.Accessibility.Protected => TrailingSpacedToken(SyntaxKind.ProtectedKeyword),
Microsoft.CodeAnalysis.Accessibility.Internal => TrailingSpacedToken(SyntaxKind.InternalKeyword),
Microsoft.CodeAnalysis.Accessibility.Public => TrailingSpacedToken(SyntaxKind.PublicKeyword),
_ => throw new ArgumentOutOfRangeException(nameof(accessibility), accessibility, null)
};
}

public static AssignmentExpressionSyntax Assignment(ExpressionSyntax target, ExpressionSyntax source)
{
return AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, target, SpacedToken(SyntaxKind.EqualsToken), source);
Expand Down
44 changes: 44 additions & 0 deletions test/Riok.Mapperly.IntegrationTests/DerivedMapperTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
using System.Threading.Tasks;
using FluentAssertions;
using Riok.Mapperly.IntegrationTests.Mapper;
using VerifyXunit;
using Xunit;

namespace Riok.Mapperly.IntegrationTests
{
[UsesVerify]
public class DerivedMapperTest : BaseMapperTest
{
[Fact]
public Task SnapshotGeneratedSourceBaseMapper()
{
var path = GetGeneratedMapperFilePath(nameof(BaseMapper));
return Verifier.VerifyFile(path);
}

[Fact]
public Task SnapshotGeneratedSourceDerivedMapper()
{
var path = GetGeneratedMapperFilePath(nameof(DerivedMapper));
return Verifier.VerifyFile(path);
}

[Fact]
public Task SnapshotGeneratedSourceDerivedMapper2()
{
var path = GetGeneratedMapperFilePath(nameof(DerivedMapper2));
return Verifier.VerifyFile(path);
}

[Fact]
public void RunMappingShouldWork()
{
new BaseMapper().IntToLong(10).Should().Be(10L);
new BaseMapper().IntToShort(10).Should().Be(10);
new DerivedMapper().IntToLong(10).Should().Be(10L);
new DerivedMapper().IntToShort(10).Should().Be(10);
new DerivedMapper2().IntToLong(10).Should().Be(10L);
new DerivedMapper2().IntToShort(10).Should().Be(10);
}
}
}
26 changes: 26 additions & 0 deletions test/Riok.Mapperly.IntegrationTests/Mapper/DerivedMapper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
using Riok.Mapperly.Abstractions;

namespace Riok.Mapperly.IntegrationTests.Mapper
{
[Mapper]
public partial class BaseMapper
{
public virtual partial long IntToLong(int value);

public partial short IntToShort(int value);
}

[Mapper]
public partial class DerivedMapper : BaseMapper
{
public override partial long IntToLong(int value);
}

[Mapper]
public partial class DerivedMapper2 : BaseMapper
{
public sealed override partial long IntToLong(int value);

public new partial short IntToShort(int value);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// <auto-generated />
#nullable enable
namespace Riok.Mapperly.IntegrationTests.Mapper
{
public partial class BaseMapper
{
public virtual partial long IntToLong(int value)
{
return (long)value;
}

public partial short IntToShort(int value)
{
return (short)value;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// <auto-generated />
#nullable enable
namespace Riok.Mapperly.IntegrationTests.Mapper
{
public partial class DerivedMapper
{
public override partial long IntToLong(int value)
{
return (long)value;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// <auto-generated />
#nullable enable
namespace Riok.Mapperly.IntegrationTests.Mapper
{
public partial class DerivedMapper2
{
public sealed override partial long IntToLong(int value)
{
return (long)value;
}

public new partial short IntToShort(int value)
{
return (short)value;
}
}
}
2 changes: 1 addition & 1 deletion test/Riok.Mapperly.Tests/Mapping/EnumTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ public void EnumToOtherEnumByNameIgnoreCaseShouldSwitch()
public Task EnumToOtherEnumByNameWithoutOverlap()
{
var source = TestSourceBuilder.MapperWithBodyAndTypes(
"[MapEnum(EnumMappingStrategy.ByName)] partial E2 ToE1(E1 source);",
"[MapEnum(EnumMappingStrategy.ByName)] private partial E2 ToE1(E1 source);",
"enum E1 {A, B, C}",
"enum E2 {D, E, F}"
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ public void EnumerableToExistingCustomCollection()
public Task MapToExistingCollectionShouldWork()
{
var source = TestSourceBuilder.MapperWithBodyAndTypes(
"partial void Map(List<A>? source, RepeatedField<B> target);",
"private partial void Map(List<A>? source, RepeatedField<B> target);",
"class RepeatedField<T> : IList<T> { public void Add(T item) {} }",
"class A { public string Value { get; set; } }",
"class B { public string Value { get; set; } }"
Expand All @@ -69,7 +69,7 @@ public void MapToExistingCollectionWithUnmappableElementsShouldDiagnostic()
public Task MapToExistingStackShouldWork()
{
var source = TestSourceBuilder.MapperWithBodyAndTypes(
"partial void Map(List<A>? source, Stack<B> target);",
"private partial void Map(List<A>? source, Stack<B> target);",
"class A { public string Value { get; set; } }",
"class B { public string Value { get; set; } }"
);
Expand All @@ -81,7 +81,7 @@ public Task MapToExistingStackShouldWork()
public Task MapToExistingQueueShouldWork()
{
var source = TestSourceBuilder.MapperWithBodyAndTypes(
"partial void Map(List<A>? source, Queue<B> target);",
"private partial void Map(List<A>? source, Queue<B> target);",
"class A { public string Value { get; set; } }",
"class B { public string Value { get; set; } }"
);
Expand Down
18 changes: 9 additions & 9 deletions test/Riok.Mapperly.Tests/Mapping/GenericTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ public Task WithGenericSourceAndTarget()
{
var source = TestSourceBuilder.MapperWithBodyAndTypes(
"""
partial TTarget Map<TSource, TTarget>(TSource source);
private partial TTarget Map<TSource, TTarget>(TSource source);

partial B MapToB(A source);
partial D MapToD(C source);
private partial B MapToB(A source);
private partial D MapToD(C source);
""",
"record struct A(string Value);",
"record struct B(string Value);",
Expand Down Expand Up @@ -435,10 +435,10 @@ public Task WithGenericSourceAndTargetAndEnabledReferenceHandling()
{
var source = TestSourceBuilder.MapperWithBodyAndTypes(
"""
partial TTarget Map<TSource, TTarget>(TSource source);
private partial TTarget Map<TSource, TTarget>(TSource source);

partial B MapToB(A source);
partial D MapToD(C source);
private partial B MapToB(A source);
private partial D MapToD(C source);
""",
TestSourceBuilderOptions.WithReferenceHandling,
"record struct A(string Value);",
Expand All @@ -454,10 +454,10 @@ public Task WithGenericSourceAndTargetAndEnabledReferenceHandlingAndParameter()
{
var source = TestSourceBuilder.MapperWithBodyAndTypes(
"""
partial TTarget Map<TSource, TTarget>(TSource source, [ReferenceHandler] IReferenceHandler refHandler);
private partial TTarget Map<TSource, TTarget>(TSource source, [ReferenceHandler] IReferenceHandler refHandler);

partial B MapToB(A source, [ReferenceHandler] IReferenceHandler refHandler);
partial D MapToD(C source, [ReferenceHandler] IReferenceHandler refHandler);
private partial B MapToB(A source, [ReferenceHandler] IReferenceHandler refHandler);
private partial D MapToD(C source, [ReferenceHandler] IReferenceHandler refHandler);
""",
TestSourceBuilderOptions.WithReferenceHandling,
"record struct A(string Value);",
Expand Down
2 changes: 1 addition & 1 deletion test/Riok.Mapperly.Tests/Mapping/MapperTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ public Task AssemblyAttributeShouldWork()
[Mapper(EnumMappingStrategy = EnumMappingStrategy.ByName)]
public partial class MyMapper
{
partial E2 Map(E1 source);
private partial E2 Map(E1 source);
}

enum E1 { value1 }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -442,7 +442,7 @@ public void ManualUnflattenedPropertyDeepNullablePath()
public Task ManualUnflattenedPropertyNullablePathNoParameterlessCtorShouldDiagnostic()
{
var source = TestSourceBuilder.MapperWithBodyAndTypes(
"[MapProperty($\"MyValueId\", \"Value.Id\")] partial B Map(A source);",
"[MapProperty($\"MyValueId\", \"Value.Id\")] private partial B Map(A source);",
"class A { public string MyValueId { get; set; } }",
"class B { public C? Value { get; set; } }",
"class C { public C(string arg) {} public string Id { get; set; } }"
Expand All @@ -455,7 +455,7 @@ public Task ManualUnflattenedPropertyNullablePathNoParameterlessCtorShouldDiagno
public Task ManualUnflattenedPropertySourcePropertyNotFoundShouldDiagnostic()
{
var source = TestSourceBuilder.MapperWithBodyAndTypes(
"[MapProperty($\"MyValueIdXXX\", \"Value.Id\")] partial B Map(A source);",
"[MapProperty($\"MyValueIdXXX\", \"Value.Id\")] private partial B Map(A source);",
"class A { public string MyValueId { get; set; } }",
"class B { public C? Value { get; set; } }",
"class C { public C(string arg) {} public string Id { get; set; } }"
Expand All @@ -468,7 +468,7 @@ public Task ManualUnflattenedPropertySourcePropertyNotFoundShouldDiagnostic()
public Task ManualUnflattenedPropertyTargetPropertyPathWriteOnlyShouldDiagnostic()
{
var source = TestSourceBuilder.MapperWithBodyAndTypes(
"[MapProperty($\"MyValueId\", \"Value.Id\")] partial B Map(A source);",
"[MapProperty($\"MyValueId\", \"Value.Id\")] private partial B Map(A source);",
"class A { public string MyValueId { get; set; } }",
"class B { public C? Value { set; } }",
"class C { public C(string arg) {} public string Id { get; set; } }"
Expand All @@ -481,7 +481,7 @@ public Task ManualUnflattenedPropertyTargetPropertyPathWriteOnlyShouldDiagnostic
public Task ManualUnflattenedPropertyTargetPropertyNotFoundShouldDiagnostic()
{
var source = TestSourceBuilder.MapperWithBodyAndTypes(
"[MapProperty($\"MyValueId\", \"Value.IdXXX\")] partial B Map(A source);",
"[MapProperty($\"MyValueId\", \"Value.IdXXX\")] private partial B Map(A source);",
"class A { public string MyValueId { get; set; } }",
"class B { public C? Value { get; set; } }",
"class C { public C(string arg) {} public string Id { get; set; } }"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ public void InitOnlyPropertySourceNotFoundShouldDiagnostic()
public Task InitOnlyPropertyWithMultipleConfigurationsShouldDiagnostic()
{
var source = TestSourceBuilder.MapperWithBodyAndTypes(
"[MapProperty($\"StringValue2\", \"StringValue\")] [MapProperty($\"StringValue3\", \"StringValue\")] partial B Map(A source);",
"[MapProperty($\"StringValue2\", \"StringValue\")] [MapProperty($\"StringValue3\", \"StringValue\")] private partial B Map(A source);",
"class A { public string StringValue2 { get; init; } public string StringValue3 { get; init; } }",
"class B { public string StringValue { get; init; } }"
);
Expand All @@ -266,7 +266,7 @@ public Task InitOnlyPropertyWithMultipleConfigurationsShouldDiagnostic()
public Task InitOnlyPropertyWithPathConfigurationsShouldDiagnostic()
{
var source = TestSourceBuilder.MapperWithBodyAndTypes(
"[MapProperty($\"NestedValue\", \"Nested.Value\")] partial B Map(A source);",
"[MapProperty($\"NestedValue\", \"Nested.Value\")] private partial B Map(A source);",
"class A { public string NestedValue { get; init; } }",
"class B { public C Nested { get; init; } }",
"class C { public string Value { get; init; } }"
Expand All @@ -279,7 +279,7 @@ public Task InitOnlyPropertyWithPathConfigurationsShouldDiagnostic()
public Task InitOnlyPropertyWithConfigurationNotFoundSourcePropertyShouldDiagnostic()
{
var source = TestSourceBuilder.MapperWithBodyAndTypes(
"[MapProperty($\"StringValue2\", \"StringValue\")] partial B Map(A source);",
"[MapProperty($\"StringValue2\", \"StringValue\")] private partial B Map(A source);",
"class A { public string StringValue { get; init; } }",
"class B { public string StringValue { get; init; } }"
);
Expand Down
8 changes: 4 additions & 4 deletions test/Riok.Mapperly.Tests/Mapping/ObjectPropertyTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ public void WithPropertyNameMappingStrategyCaseInsensitive()
public Task WithPropertyNameMappingStrategyCaseSensitive()
{
var source = TestSourceBuilder.MapperWithBodyAndTypes(
"partial B Map(A source);",
"private partial B Map(A source);",
new TestSourceBuilderOptions { PropertyNameMappingStrategy = PropertyNameMappingStrategy.CaseSensitive },
"class A { public string StringValue { get; set; } }",
"class B { public string stringvalue { get; set; } }"
Expand All @@ -212,7 +212,7 @@ public Task WithPropertyNameMappingStrategyCaseSensitive()
public Task WithManualMappedNotFoundTargetPropertyShouldDiagnostic()
{
var source = TestSourceBuilder.MapperWithBodyAndTypes(
"[MapProperty(nameof(A.StringValue), nameof(B.StringValue9)] partial B Map(A source);",
"[MapProperty(nameof(A.StringValue), nameof(B.StringValue9)] private partial B Map(A source);",
"class A { public string StringValue { get; set; } }",
"class B { public string StringValue2 { get; set; } }"
);
Expand All @@ -224,7 +224,7 @@ public Task WithManualMappedNotFoundTargetPropertyShouldDiagnostic()
public Task WithManualMappedNotFoundSourcePropertyShouldDiagnostic()
{
var source = TestSourceBuilder.MapperWithBodyAndTypes(
"[MapProperty(\"StringValue9\", nameof(B.StringValue2)] partial B Map(A source);",
"[MapProperty(\"StringValue9\", nameof(B.StringValue2)] private partial B Map(A source);",
"class A { public string StringValue { get; set; } }",
"class B { public string StringValue2 { get; set; } }"
);
Expand Down Expand Up @@ -296,7 +296,7 @@ public Task WithManualNotFoundTargetPropertyShouldDiagnostic()
public Task WithManualNotFoundSourcePropertyShouldDiagnostic()
{
var source = TestSourceBuilder.MapperWithBodyAndTypes(
"[MapProperty(\"not_found\", nameof(B.StringValue2))] partial B Map(A source);",
"[MapProperty(\"not_found\", nameof(B.StringValue2))] private partial B Map(A source);",
"class A { public string StringValue { get; set; } }",
"class B { public string StringValue2 { get; set; } }"
);
Expand Down
Loading

0 comments on commit 2087ca4

Please sign in to comment.