diff --git a/src/Riok.Mapperly/Descriptors/MappingBodyBuilders/RuntimeTargetTypeMappingBodyBuilder.cs b/src/Riok.Mapperly/Descriptors/MappingBodyBuilders/RuntimeTargetTypeMappingBodyBuilder.cs index cc92fee709..832ecc36dc 100644 --- a/src/Riok.Mapperly/Descriptors/MappingBodyBuilders/RuntimeTargetTypeMappingBodyBuilder.cs +++ b/src/Riok.Mapperly/Descriptors/MappingBodyBuilders/RuntimeTargetTypeMappingBodyBuilder.cs @@ -39,7 +39,7 @@ private static IEnumerable GetUserMappingCandidates(MappingBuilder foreach (var userMapping in ctx.UserMappings) { // exclude runtime target type mappings - if (userMapping is UserDefinedNewInstanceRuntimeTargetTypeMapping) + if (userMapping is UserDefinedNewInstanceRuntimeTargetTypeMapping or UserImplementedExistingTargetMethodMapping) continue; if (userMapping.CallableByOtherMappings) diff --git a/src/Riok.Mapperly/Descriptors/MappingCollection.cs b/src/Riok.Mapperly/Descriptors/MappingCollection.cs index 9bceccae3a..19ec7746b0 100644 --- a/src/Riok.Mapperly/Descriptors/MappingCollection.cs +++ b/src/Riok.Mapperly/Descriptors/MappingCollection.cs @@ -66,13 +66,12 @@ public void Add(ITypeMapping mapping) _methodMappings.Add(methodMapping); } - if ( - mapping.CallableByOtherMappings - && mapping is UserImplementedExistingTargetMethodMapping existingMapping - && FindExistingInstanceMapping(mapping.SourceType, mapping.TargetType) is null - ) + if (mapping.CallableByOtherMappings && mapping is UserImplementedExistingTargetMethodMapping existingMapping) { - _existingTargetMappings.Add(new TypeMappingKey(mapping), existingMapping); + if (FindExistingInstanceMapping(mapping.SourceType, mapping.TargetType) is null) + { + _existingTargetMappings.Add(new TypeMappingKey(mapping), existingMapping); + } return; } diff --git a/src/Riok.Mapperly/Descriptors/Mappings/UserMappings/UserImplementedExistingTargetMethodMapping.cs b/src/Riok.Mapperly/Descriptors/Mappings/UserMappings/UserImplementedExistingTargetMethodMapping.cs index a366da607b..2244047b85 100644 --- a/src/Riok.Mapperly/Descriptors/Mappings/UserMappings/UserImplementedExistingTargetMethodMapping.cs +++ b/src/Riok.Mapperly/Descriptors/Mappings/UserMappings/UserImplementedExistingTargetMethodMapping.cs @@ -37,7 +37,9 @@ public UserImplementedExistingTargetMethodMapping( public bool IsSynthetic => false; public ExpressionSyntax Build(TypeMappingBuildContext ctx) => - throw new InvalidOperationException($"{nameof(UserDefinedExistingTargetMethodMapping)} does not support {nameof(Build)}"); + throw new InvalidOperationException( + $"{nameof(UserImplementedExistingTargetMethodMapping)} {ctx.Source}, {ctx.ReferenceHandler} does not support {nameof(Build)}" + ); public override IEnumerable Build(TypeMappingBuildContext ctx, ExpressionSyntax target) { diff --git a/test/Riok.Mapperly.IntegrationTests/BaseMapperTest.cs b/test/Riok.Mapperly.IntegrationTests/BaseMapperTest.cs index 0eaa946613..8e547c30f3 100644 --- a/test/Riok.Mapperly.IntegrationTests/BaseMapperTest.cs +++ b/test/Riok.Mapperly.IntegrationTests/BaseMapperTest.cs @@ -109,6 +109,7 @@ public static TestObject NewTestObj() ExistingISet = { "1", "2", "3", }, ExistingHashSet = { "1", "2", "3", }, ExistingSortedSet = { "1", "2", "3", }, + ExistingList = { "1", "2", "3", }, ISet = new HashSet { "1", "2", "3", }, #if NET5_0_OR_GREATER IReadOnlySet = new HashSet { "1", "2", "3", }, diff --git a/test/Riok.Mapperly.IntegrationTests/Dto/TestObjectDto.cs b/test/Riok.Mapperly.IntegrationTests/Dto/TestObjectDto.cs index 2e0c554ea2..ea814ea60f 100644 --- a/test/Riok.Mapperly.IntegrationTests/Dto/TestObjectDto.cs +++ b/test/Riok.Mapperly.IntegrationTests/Dto/TestObjectDto.cs @@ -79,9 +79,11 @@ public TestObjectDto(int ctorValue, int unknownValue = 10, int ctorValue2 = 100) public ISet ExistingISet { get; } = new HashSet(); - public HashSet ExistingHashSet { get; } = new HashSet(); + public HashSet ExistingHashSet { get; } = new(); - public SortedSet ExistingSortedSet { get; } = new SortedSet(); + public SortedSet ExistingSortedSet { get; } = new(); + + public List ExistingList { get; } = new(); public ISet ISet { get; set; } = new HashSet(); diff --git a/test/Riok.Mapperly.IntegrationTests/Mapper/StaticTestMapper.cs b/test/Riok.Mapperly.IntegrationTests/Mapper/StaticTestMapper.cs index 84c41bbf12..ffe5161dd3 100644 --- a/test/Riok.Mapperly.IntegrationTests/Mapper/StaticTestMapper.cs +++ b/test/Riok.Mapperly.IntegrationTests/Mapper/StaticTestMapper.cs @@ -38,6 +38,15 @@ public static TestObjectDto MapToDto(TestObject src) return target; } + public static void MapExistingList(List src, List dst) + { + dst.EnsureCapacity(src.Count + dst.Count); + foreach (var item in src) + { + dst.Add(int.Parse(item)); + } + } + // disable obsolete warning, as the obsolete attribute should still be tested. #pragma warning disable CS0618 [MapperIgnore(nameof(TestObjectDto.IgnoredStringValue))] diff --git a/test/Riok.Mapperly.IntegrationTests/Models/TestObject.cs b/test/Riok.Mapperly.IntegrationTests/Models/TestObject.cs index c01df23838..86605edc40 100644 --- a/test/Riok.Mapperly.IntegrationTests/Models/TestObject.cs +++ b/test/Riok.Mapperly.IntegrationTests/Models/TestObject.cs @@ -77,9 +77,11 @@ public TestObject(int ctorValue, int unknownValue = 10, int ctorValue2 = 100) public ISet ExistingISet { get; } = new HashSet(); - public HashSet ExistingHashSet { get; } = new HashSet(); + public HashSet ExistingHashSet { get; } = new(); - public SortedSet ExistingSortedSet { get; } = new SortedSet(); + public SortedSet ExistingSortedSet { get; } = new(); + + public List ExistingList { get; } = new(); public ISet ISet { get; set; } = new HashSet(); diff --git a/test/Riok.Mapperly.IntegrationTests/_snapshots/NET_48/MapperTest.RunMappingShouldWork.verified.txt b/test/Riok.Mapperly.IntegrationTests/_snapshots/NET_48/MapperTest.RunMappingShouldWork.verified.txt index 6f6e920259..d176ba58f4 100644 --- a/test/Riok.Mapperly.IntegrationTests/_snapshots/NET_48/MapperTest.RunMappingShouldWork.verified.txt +++ b/test/Riok.Mapperly.IntegrationTests/_snapshots/NET_48/MapperTest.RunMappingShouldWork.verified.txt @@ -56,7 +56,7 @@ ImmutableArrayValue: null, ImmutableQueueValue: [], ImmutableStackValue: [], - EnumReverseStringValue: + EnumReverseStringValue: }, NullableReadOnlyObjectCollection: [ { diff --git a/test/Riok.Mapperly.IntegrationTests/_snapshots/Roslyn_4_5/DeepCloningMapperTest.RunMappingShouldWork.verified.txt b/test/Riok.Mapperly.IntegrationTests/_snapshots/Roslyn_4_5/DeepCloningMapperTest.RunMappingShouldWork.verified.txt index 90335d9b16..def9404732 100644 --- a/test/Riok.Mapperly.IntegrationTests/_snapshots/Roslyn_4_5/DeepCloningMapperTest.RunMappingShouldWork.verified.txt +++ b/test/Riok.Mapperly.IntegrationTests/_snapshots/Roslyn_4_5/DeepCloningMapperTest.RunMappingShouldWork.verified.txt @@ -124,6 +124,11 @@ 2, 3 ], + ExistingList: [ + 1, + 2, + 3 + ], ISet: [ 1, 2, diff --git a/test/Riok.Mapperly.IntegrationTests/_snapshots/Roslyn_4_5/DeepCloningMapperTest.SnapshotGeneratedSource.verified.cs b/test/Riok.Mapperly.IntegrationTests/_snapshots/Roslyn_4_5/DeepCloningMapperTest.SnapshotGeneratedSource.verified.cs index df5b5c8a04..030736aa6e 100644 --- a/test/Riok.Mapperly.IntegrationTests/_snapshots/Roslyn_4_5/DeepCloningMapperTest.SnapshotGeneratedSource.verified.cs +++ b/test/Riok.Mapperly.IntegrationTests/_snapshots/Roslyn_4_5/DeepCloningMapperTest.SnapshotGeneratedSource.verified.cs @@ -86,6 +86,12 @@ public static partial class DeepCloningMapper target.ExistingSortedSet.Add(item2); } + target.ExistingList.EnsureCapacity(src.ExistingList.Count + target.ExistingList.Count); + foreach (var item3 in src.ExistingList) + { + target.ExistingList.Add(item3); + } + target.ISet = global::System.Linq.Enumerable.ToHashSet(src.ISet); target.IReadOnlySet = global::System.Linq.Enumerable.ToHashSet(src.IReadOnlySet); target.HashSet = global::System.Linq.Enumerable.ToHashSet(src.HashSet); diff --git a/test/Riok.Mapperly.IntegrationTests/_snapshots/Roslyn_4_5/MapperTest.RunMappingShouldWork.verified.txt b/test/Riok.Mapperly.IntegrationTests/_snapshots/Roslyn_4_5/MapperTest.RunMappingShouldWork.verified.txt index 4d03e0e639..262da34565 100644 --- a/test/Riok.Mapperly.IntegrationTests/_snapshots/Roslyn_4_5/MapperTest.RunMappingShouldWork.verified.txt +++ b/test/Riok.Mapperly.IntegrationTests/_snapshots/Roslyn_4_5/MapperTest.RunMappingShouldWork.verified.txt @@ -140,6 +140,11 @@ 2, 3 ], + ExistingList: [ + 1, + 2, + 3 + ], ISet: [ 1, 2, diff --git a/test/Riok.Mapperly.IntegrationTests/_snapshots/Roslyn_4_5/MapperTest.SnapshotGeneratedSource.verified.cs b/test/Riok.Mapperly.IntegrationTests/_snapshots/Roslyn_4_5/MapperTest.SnapshotGeneratedSource.verified.cs index 6045c2198d..66028394e4 100644 --- a/test/Riok.Mapperly.IntegrationTests/_snapshots/Roslyn_4_5/MapperTest.SnapshotGeneratedSource.verified.cs +++ b/test/Riok.Mapperly.IntegrationTests/_snapshots/Roslyn_4_5/MapperTest.SnapshotGeneratedSource.verified.cs @@ -127,6 +127,12 @@ public partial int ParseableInt(string value) target.ExistingSortedSet.Add(ParseableInt(item2)); } + target.ExistingList.EnsureCapacity(testObject.ExistingList.Count + target.ExistingList.Count); + foreach (var item3 in testObject.ExistingList) + { + target.ExistingList.Add(ParseableInt(item3)); + } + target.ISet = global::System.Linq.Enumerable.ToHashSet(global::System.Linq.Enumerable.Select(testObject.ISet, x => ParseableInt(x))); target.IReadOnlySet = global::System.Linq.Enumerable.ToHashSet(global::System.Linq.Enumerable.Select(testObject.IReadOnlySet, x => ParseableInt(x))); target.HashSet = global::System.Linq.Enumerable.ToHashSet(global::System.Linq.Enumerable.Select(testObject.HashSet, x => ParseableInt(x))); @@ -211,6 +217,12 @@ public partial int ParseableInt(string value) target.ExistingSortedSet.Add(item2.ToString()); } + target.ExistingList.EnsureCapacity(dto.ExistingList.Count + target.ExistingList.Count); + foreach (var item3 in dto.ExistingList) + { + target.ExistingList.Add(item3.ToString()); + } + target.ISet = global::System.Linq.Enumerable.ToHashSet(global::System.Linq.Enumerable.Select(dto.ISet, x => x.ToString())); target.IReadOnlySet = global::System.Linq.Enumerable.ToHashSet(global::System.Linq.Enumerable.Select(dto.IReadOnlySet, x => x.ToString())); target.HashSet = global::System.Linq.Enumerable.ToHashSet(global::System.Linq.Enumerable.Select(dto.HashSet, x => x.ToString())); @@ -296,6 +308,12 @@ public partial void UpdateDto(global::Riok.Mapperly.IntegrationTests.Models.Test target.ExistingSortedSet.Add(ParseableInt(item2)); } + target.ExistingList.EnsureCapacity(source.ExistingList.Count + target.ExistingList.Count); + foreach (var item3 in source.ExistingList) + { + target.ExistingList.Add(ParseableInt(item3)); + } + target.ISet = global::System.Linq.Enumerable.ToHashSet(global::System.Linq.Enumerable.Select(source.ISet, x => ParseableInt(x))); target.IReadOnlySet = global::System.Linq.Enumerable.ToHashSet(global::System.Linq.Enumerable.Select(source.IReadOnlySet, x => ParseableInt(x))); target.HashSet = global::System.Linq.Enumerable.ToHashSet(global::System.Linq.Enumerable.Select(source.HashSet, x => ParseableInt(x))); @@ -444,4 +462,4 @@ private string MapToString1(global::Riok.Mapperly.IntegrationTests.Dto.TestEnumD return target; } } -} \ No newline at end of file +} diff --git a/test/Riok.Mapperly.IntegrationTests/_snapshots/Roslyn_4_5/StaticMapperTest.RunExtensionMappingShouldWork.verified.txt b/test/Riok.Mapperly.IntegrationTests/_snapshots/Roslyn_4_5/StaticMapperTest.RunExtensionMappingShouldWork.verified.txt index d0a7271d51..f8d7742c71 100644 --- a/test/Riok.Mapperly.IntegrationTests/_snapshots/Roslyn_4_5/StaticMapperTest.RunExtensionMappingShouldWork.verified.txt +++ b/test/Riok.Mapperly.IntegrationTests/_snapshots/Roslyn_4_5/StaticMapperTest.RunExtensionMappingShouldWork.verified.txt @@ -135,6 +135,11 @@ 2, 3 ], + ExistingList: [ + 1, + 2, + 3 + ], ISet: [ 1, 2, diff --git a/test/Riok.Mapperly.IntegrationTests/_snapshots/Roslyn_4_5/StaticMapperTest.RunMappingShouldWork.verified.txt b/test/Riok.Mapperly.IntegrationTests/_snapshots/Roslyn_4_5/StaticMapperTest.RunMappingShouldWork.verified.txt index 5ade304416..b764ab8d8d 100644 --- a/test/Riok.Mapperly.IntegrationTests/_snapshots/Roslyn_4_5/StaticMapperTest.RunMappingShouldWork.verified.txt +++ b/test/Riok.Mapperly.IntegrationTests/_snapshots/Roslyn_4_5/StaticMapperTest.RunMappingShouldWork.verified.txt @@ -140,6 +140,11 @@ 2, 3 ], + ExistingList: [ + 1, + 2, + 3 + ], ISet: [ 1, 2, diff --git a/test/Riok.Mapperly.IntegrationTests/_snapshots/Roslyn_4_5/StaticMapperTest.SnapshotGeneratedSource.verified.cs b/test/Riok.Mapperly.IntegrationTests/_snapshots/Roslyn_4_5/StaticMapperTest.SnapshotGeneratedSource.verified.cs index 699997e00c..07cb72804a 100644 --- a/test/Riok.Mapperly.IntegrationTests/_snapshots/Roslyn_4_5/StaticMapperTest.SnapshotGeneratedSource.verified.cs +++ b/test/Riok.Mapperly.IntegrationTests/_snapshots/Roslyn_4_5/StaticMapperTest.SnapshotGeneratedSource.verified.cs @@ -124,6 +124,7 @@ public static partial int ParseableInt(string value) target.ExistingSortedSet.Add(ParseableInt(item2)); } + MapExistingList(src.ExistingList, target.ExistingList); target.ISet = global::System.Linq.Enumerable.ToHashSet(global::System.Linq.Enumerable.Select(src.ISet, x => ParseableInt(x))); target.IReadOnlySet = global::System.Linq.Enumerable.ToHashSet(global::System.Linq.Enumerable.Select(src.IReadOnlySet, x => ParseableInt(x))); target.HashSet = global::System.Linq.Enumerable.ToHashSet(global::System.Linq.Enumerable.Select(src.HashSet, x => ParseableInt(x))); @@ -222,6 +223,7 @@ public static partial int ParseableInt(string value) target.ExistingSortedSet.Add(ParseableInt(item2)); } + MapExistingList(testObject.ExistingList, target.ExistingList); target.ISet = global::System.Linq.Enumerable.ToHashSet(global::System.Linq.Enumerable.Select(testObject.ISet, x => ParseableInt(x))); target.IReadOnlySet = global::System.Linq.Enumerable.ToHashSet(global::System.Linq.Enumerable.Select(testObject.IReadOnlySet, x => ParseableInt(x))); target.HashSet = global::System.Linq.Enumerable.ToHashSet(global::System.Linq.Enumerable.Select(testObject.HashSet, x => ParseableInt(x))); @@ -306,6 +308,12 @@ public static partial int ParseableInt(string value) target.ExistingSortedSet.Add(item2.ToString()); } + target.ExistingList.EnsureCapacity(dto.ExistingList.Count + target.ExistingList.Count); + foreach (var item3 in dto.ExistingList) + { + target.ExistingList.Add(item3.ToString()); + } + target.ISet = global::System.Linq.Enumerable.ToHashSet(global::System.Linq.Enumerable.Select(dto.ISet, x => x.ToString())); target.IReadOnlySet = global::System.Linq.Enumerable.ToHashSet(global::System.Linq.Enumerable.Select(dto.IReadOnlySet, x => x.ToString())); target.HashSet = global::System.Linq.Enumerable.ToHashSet(global::System.Linq.Enumerable.Select(dto.HashSet, x => x.ToString())); @@ -391,6 +399,7 @@ public static partial void UpdateDto(global::Riok.Mapperly.IntegrationTests.Mode target.ExistingSortedSet.Add(ParseableInt(item2)); } + MapExistingList(source.ExistingList, target.ExistingList); target.ISet = global::System.Linq.Enumerable.ToHashSet(global::System.Linq.Enumerable.Select(source.ISet, x => ParseableInt(x))); target.IReadOnlySet = global::System.Linq.Enumerable.ToHashSet(global::System.Linq.Enumerable.Select(source.IReadOnlySet, x => ParseableInt(x))); target.HashSet = global::System.Linq.Enumerable.ToHashSet(global::System.Linq.Enumerable.Select(source.HashSet, x => ParseableInt(x)));