diff --git a/src/Riok.Mapperly/Descriptors/InlineExpressionMappingBuilderContext.cs b/src/Riok.Mapperly/Descriptors/InlineExpressionMappingBuilderContext.cs index d32f2aed58..200ddb49fc 100644 --- a/src/Riok.Mapperly/Descriptors/InlineExpressionMappingBuilderContext.cs +++ b/src/Riok.Mapperly/Descriptors/InlineExpressionMappingBuilderContext.cs @@ -61,8 +61,8 @@ conversionType is not MappingConversionType.EnumToString and not MappingConversi /// /// The source type. /// The target type. - /// The if a mapping was found or null if none was found. - public override ITypeMapping? FindMapping(ITypeSymbol sourceType, ITypeSymbol targetType) + /// The if a mapping was found or null if none was found. + public override INewInstanceMapping? FindMapping(ITypeSymbol sourceType, ITypeSymbol targetType) { if (_inlineExpressionMappings.Find(sourceType, targetType) is { } mapping) return mapping; @@ -92,7 +92,7 @@ conversionType is not MappingConversionType.EnumToString and not MappingConversi /// The target type. /// The options, is ignored. /// - public override ITypeMapping? FindOrBuildMapping( + public override INewInstanceMapping? FindOrBuildMapping( ITypeSymbol sourceType, ITypeSymbol targetType, MappingBuildingOptions options = MappingBuildingOptions.Default diff --git a/src/Riok.Mapperly/Descriptors/MappingBodyBuilders/RuntimeTargetTypeMappingBodyBuilder.cs b/src/Riok.Mapperly/Descriptors/MappingBodyBuilders/RuntimeTargetTypeMappingBodyBuilder.cs index e2ce7394a3..e4457e908e 100644 --- a/src/Riok.Mapperly/Descriptors/MappingBodyBuilders/RuntimeTargetTypeMappingBodyBuilder.cs +++ b/src/Riok.Mapperly/Descriptors/MappingBodyBuilders/RuntimeTargetTypeMappingBodyBuilder.cs @@ -45,7 +45,7 @@ private static IEnumerable GetUserMappingCandidates(MappingBuilder { foreach (var userMapping in ctx.UserMappings) { - // exclude runtime target type mappings + // exclude runtime target type if (userMapping is UserDefinedNewInstanceRuntimeTargetTypeMapping) continue; @@ -76,6 +76,7 @@ IEnumerable childMappings // in the type switch // to use the most specific mapping var runtimeTargetTypeMappings = childMappings + .OfType() .OrderByDescending(x => x.SourceType.GetInheritanceLevel()) .ThenByDescending(x => x.TargetType.GetInheritanceLevel()) .ThenBy(x => x.TargetType.IsNullable()) diff --git a/src/Riok.Mapperly/Descriptors/MappingBuilderContext.cs b/src/Riok.Mapperly/Descriptors/MappingBuilderContext.cs index eba5a5afd3..26ee3e07f9 100644 --- a/src/Riok.Mapperly/Descriptors/MappingBuilderContext.cs +++ b/src/Riok.Mapperly/Descriptors/MappingBuilderContext.cs @@ -74,7 +74,7 @@ bool clearDerivedTypes /// The source type. /// The target type. /// The found mapping, or null if none is found. - public virtual ITypeMapping? FindMapping(ITypeSymbol sourceType, ITypeSymbol targetType) => + public virtual INewInstanceMapping? FindMapping(ITypeSymbol sourceType, ITypeSymbol targetType) => MappingBuilder.Find(sourceType.UpgradeNullable(), targetType.UpgradeNullable()); /// @@ -90,7 +90,7 @@ bool clearDerivedTypes /// The target type. /// The mapping building options. /// The found or created mapping, or null if no mapping could be created. - public virtual ITypeMapping? FindOrBuildMapping( + public virtual INewInstanceMapping? FindOrBuildMapping( ITypeSymbol sourceType, ITypeSymbol targetType, MappingBuildingOptions options = MappingBuildingOptions.Default @@ -108,7 +108,7 @@ bool clearDerivedTypes /// The target type. /// The options. /// The created mapping, or null if no mapping could be created. - public ITypeMapping? BuildMapping(ITypeSymbol source, ITypeSymbol target, MappingBuildingOptions options) + public INewInstanceMapping? BuildMapping(ITypeSymbol source, ITypeSymbol target, MappingBuildingOptions options) { var userSymbol = options.HasFlag(MappingBuildingOptions.KeepUserSymbol) ? UserSymbol : null; return BuildMapping(userSymbol, source, target, options); @@ -193,7 +193,7 @@ MappingBuildingOptions options return new(this, userSymbol, sourceType, targetType, options.HasFlag(MappingBuildingOptions.ClearDerivedTypes)); } - protected ITypeMapping? BuildMapping( + protected INewInstanceMapping? BuildMapping( IMethodSymbol? userSymbol, ITypeSymbol sourceType, ITypeSymbol targetType, diff --git a/src/Riok.Mapperly/Descriptors/MappingBuilders/DerivedTypeMappingBuilder.cs b/src/Riok.Mapperly/Descriptors/MappingBuilders/DerivedTypeMappingBuilder.cs index 45e7d36482..1ebf6798c8 100644 --- a/src/Riok.Mapperly/Descriptors/MappingBuilders/DerivedTypeMappingBuilder.cs +++ b/src/Riok.Mapperly/Descriptors/MappingBuilders/DerivedTypeMappingBuilder.cs @@ -8,7 +8,7 @@ namespace Riok.Mapperly.Descriptors.MappingBuilders; public static class DerivedTypeMappingBuilder { - public static ITypeMapping? TryBuildMapping(MappingBuilderContext ctx) + public static INewInstanceMapping? TryBuildMapping(MappingBuilderContext ctx) { var derivedTypeMappings = TryBuildContainedMappings(ctx); if (derivedTypeMappings == null) @@ -19,7 +19,7 @@ public static class DerivedTypeMappingBuilder : new DerivedTypeSwitchMapping(ctx.Source, ctx.Target, derivedTypeMappings); } - public static IReadOnlyCollection? TryBuildContainedMappings( + public static IReadOnlyCollection? TryBuildContainedMappings( MappingBuilderContext ctx, bool duplicatedSourceTypesAllowed = false ) @@ -29,14 +29,14 @@ public static class DerivedTypeMappingBuilder : BuildContainedMappings(ctx, ctx.Configuration.DerivedTypes, duplicatedSourceTypesAllowed); } - private static IReadOnlyCollection BuildContainedMappings( + private static IReadOnlyCollection BuildContainedMappings( MappingBuilderContext ctx, IReadOnlyCollection configs, bool duplicatedSourceTypesAllowed ) { var derivedTypeMappingSourceTypes = new HashSet(SymbolEqualityComparer.Default); - var derivedTypeMappings = new List(configs.Count); + var derivedTypeMappings = new List(configs.Count); Func isAssignableToSource = ctx.Source is ITypeParameterSymbol sourceTypeParameter ? t => ctx.SymbolAccessor.DoesTypeSatisfyTypeParameterConstraints(sourceTypeParameter, t, ctx.Source.NullableAnnotation) : t => ctx.SymbolAccessor.HasImplicitConversion(t, ctx.Source); diff --git a/src/Riok.Mapperly/Descriptors/MappingBuilders/DictionaryMappingBuilder.cs b/src/Riok.Mapperly/Descriptors/MappingBuilders/DictionaryMappingBuilder.cs index 53323a8354..dd06a6d6e1 100644 --- a/src/Riok.Mapperly/Descriptors/MappingBuilders/DictionaryMappingBuilder.cs +++ b/src/Riok.Mapperly/Descriptors/MappingBuilders/DictionaryMappingBuilder.cs @@ -18,7 +18,7 @@ public static class DictionaryMappingBuilder private const string ToImmutableSortedDictionaryMethodName = "global::System.Collections.Immutable.ImmutableSortedDictionary.ToImmutableSortedDictionary"; - public static ITypeMapping? TryBuildMapping(MappingBuilderContext ctx) + public static INewInstanceMapping? TryBuildMapping(MappingBuilderContext ctx) { if (!ctx.IsConversionEnabled(MappingConversionType.Dictionary)) return null; @@ -117,7 +117,7 @@ or CollectionType.IReadOnlyDictionary ); } - private static (ITypeMapping, ITypeMapping)? BuildKeyValueMapping(MappingBuilderContext ctx) + private static (INewInstanceMapping, INewInstanceMapping)? BuildKeyValueMapping(MappingBuilderContext ctx) { if (ctx.CollectionInfos!.Target.GetDictionaryKeyValueTypes(ctx) is not var (targetKeyType, targetValueType)) return null; @@ -153,8 +153,8 @@ out var isExplicit private static LinqDictionaryMapping? ResolveImmutableCollectMethod( MappingBuilderContext ctx, - ITypeMapping keyMapping, - ITypeMapping valueMapping + INewInstanceMapping keyMapping, + INewInstanceMapping valueMapping ) { return ctx.CollectionInfos!.Target.CollectionType switch diff --git a/src/Riok.Mapperly/Descriptors/MappingBuilders/DirectAssignmentMappingBuilder.cs b/src/Riok.Mapperly/Descriptors/MappingBuilders/DirectAssignmentMappingBuilder.cs index 84fcd117c5..ee38f04f6b 100644 --- a/src/Riok.Mapperly/Descriptors/MappingBuilders/DirectAssignmentMappingBuilder.cs +++ b/src/Riok.Mapperly/Descriptors/MappingBuilders/DirectAssignmentMappingBuilder.cs @@ -6,7 +6,7 @@ namespace Riok.Mapperly.Descriptors.MappingBuilders; public static class DirectAssignmentMappingBuilder { - public static TypeMapping? TryBuildMapping(MappingBuilderContext ctx) + public static NewInstanceMapping? TryBuildMapping(MappingBuilderContext ctx) { return SymbolEqualityComparer.IncludeNullability.Equals(ctx.Source, ctx.Target) diff --git a/src/Riok.Mapperly/Descriptors/MappingBuilders/EnumMappingBuilder.cs b/src/Riok.Mapperly/Descriptors/MappingBuilders/EnumMappingBuilder.cs index 5a4c8a09fc..801980e308 100644 --- a/src/Riok.Mapperly/Descriptors/MappingBuilders/EnumMappingBuilder.cs +++ b/src/Riok.Mapperly/Descriptors/MappingBuilders/EnumMappingBuilder.cs @@ -9,7 +9,7 @@ namespace Riok.Mapperly.Descriptors.MappingBuilders; public static class EnumMappingBuilder { - public static TypeMapping? TryBuildMapping(MappingBuilderContext ctx) + public static NewInstanceMapping? TryBuildMapping(MappingBuilderContext ctx) { var sourceIsEnum = ctx.Source.TryGetEnumUnderlyingType(out var sourceEnumType); var targetIsEnum = ctx.Target.TryGetEnumUnderlyingType(out var targetEnumType); @@ -44,7 +44,7 @@ public static class EnumMappingBuilder }; } - private static TypeMapping BuildCastMappingAndDiagnostic(MappingBuilderContext ctx) + private static NewInstanceMapping BuildCastMappingAndDiagnostic(MappingBuilderContext ctx) { ctx.ReportDiagnostic( DiagnosticDescriptors.EnumMappingNotSupportedInProjectionMappings, @@ -54,7 +54,7 @@ private static TypeMapping BuildCastMappingAndDiagnostic(MappingBuilderContext c return BuildEnumToEnumCastMapping(ctx, true); } - private static TypeMapping BuildEnumToEnumCastMapping( + private static NewInstanceMapping BuildEnumToEnumCastMapping( MappingBuilderContext ctx, bool ignoreExplicitAndIgnoredMappings = false, bool checkTargetDefined = false diff --git a/src/Riok.Mapperly/Descriptors/MappingBuilders/EnumToStringMappingBuilder.cs b/src/Riok.Mapperly/Descriptors/MappingBuilders/EnumToStringMappingBuilder.cs index 146239d801..a2a8ca7d52 100644 --- a/src/Riok.Mapperly/Descriptors/MappingBuilders/EnumToStringMappingBuilder.cs +++ b/src/Riok.Mapperly/Descriptors/MappingBuilders/EnumToStringMappingBuilder.cs @@ -8,7 +8,7 @@ namespace Riok.Mapperly.Descriptors.MappingBuilders; public static class EnumToStringMappingBuilder { - public static TypeMapping? TryBuildMapping(MappingBuilderContext ctx) + public static NewInstanceMapping? TryBuildMapping(MappingBuilderContext ctx) { if (!ctx.IsConversionEnabled(MappingConversionType.EnumToString)) return null; diff --git a/src/Riok.Mapperly/Descriptors/MappingBuilders/EnumerableMappingBuilder.cs b/src/Riok.Mapperly/Descriptors/MappingBuilders/EnumerableMappingBuilder.cs index 59ce5be273..55f56acccb 100644 --- a/src/Riok.Mapperly/Descriptors/MappingBuilders/EnumerableMappingBuilder.cs +++ b/src/Riok.Mapperly/Descriptors/MappingBuilders/EnumerableMappingBuilder.cs @@ -25,7 +25,7 @@ public static class EnumerableMappingBuilder private const string CreateRangeStackMethodName = "global::System.Collections.Immutable.ImmutableStack.CreateRange"; private const string ToImmutableSortedSetMethodName = "global::System.Collections.Immutable.ImmutableSortedSet.ToImmutableSortedSet"; - public static TypeMapping? TryBuildMapping(MappingBuilderContext ctx) + public static NewInstanceMapping? TryBuildMapping(MappingBuilderContext ctx) { if (!ctx.IsConversionEnabled(MappingConversionType.Enumerable)) return null; @@ -134,7 +134,11 @@ ForEachAddEnumerableExistingTargetMapping CreateForEach(string methodName) } } - private static LinqEnumerableMapping BuildLinqMapping(MappingBuilderContext ctx, ITypeMapping elementMapping, string? collectMethod) + private static LinqEnumerableMapping BuildLinqMapping( + MappingBuilderContext ctx, + INewInstanceMapping elementMapping, + string? collectMethod + ) { var selectMethod = elementMapping.IsSynthetic ? null : SelectMethodName; return new LinqEnumerableMapping(ctx.Source, ctx.Target, elementMapping, selectMethod, collectMethod); @@ -161,14 +165,14 @@ private static LinqEnumerableMapping BuildLinqMapping(MappingBuilderContext ctx, private static LinqConstructorMapping BuildLinqConstructorMapping( MappingBuilderContext ctx, INamedTypeSymbol targetTypeToConstruct, - ITypeMapping elementMapping + INewInstanceMapping elementMapping ) { var selectMethod = elementMapping.IsSynthetic ? null : SelectMethodName; return new LinqConstructorMapping(ctx.Source, ctx.Target, targetTypeToConstruct, elementMapping, selectMethod); } - private static ExistingTargetMappingMethodWrapper? BuildCustomTypeMapping(MappingBuilderContext ctx, ITypeMapping elementMapping) + private static ExistingTargetMappingMethodWrapper? BuildCustomTypeMapping(MappingBuilderContext ctx, INewInstanceMapping elementMapping) { if ( !ctx.ObjectFactories.TryFindObjectFactory(ctx.Source, ctx.Target, out var objectFactory) @@ -241,7 +245,7 @@ or CollectionType.ICollection : (false, null); } - private static LinqEnumerableMapping? TryBuildImmutableLinqMapping(MappingBuilderContext ctx, ITypeMapping elementMapping) + private static LinqEnumerableMapping? TryBuildImmutableLinqMapping(MappingBuilderContext ctx, INewInstanceMapping elementMapping) { var collectMethod = ResolveImmutableCollectMethod(ctx); if (collectMethod is null) diff --git a/src/Riok.Mapperly/Descriptors/MappingBuilders/MappingBuilder.cs b/src/Riok.Mapperly/Descriptors/MappingBuilders/MappingBuilder.cs index c14a52d0aa..791759253f 100644 --- a/src/Riok.Mapperly/Descriptors/MappingBuilders/MappingBuilder.cs +++ b/src/Riok.Mapperly/Descriptors/MappingBuilders/MappingBuilder.cs @@ -6,7 +6,7 @@ namespace Riok.Mapperly.Descriptors.MappingBuilders; public class MappingBuilder { - private delegate ITypeMapping? BuildMapping(MappingBuilderContext context); + private delegate INewInstanceMapping? BuildMapping(MappingBuilderContext context); private static readonly IReadOnlyCollection _builders = new BuildMapping[] { @@ -43,9 +43,9 @@ public MappingBuilder(MappingCollection mappings) public IReadOnlyCollection UserMappings => _mappings.UserMappings; /// - public ITypeMapping? Find(ITypeSymbol sourceType, ITypeSymbol targetType) => _mappings.Find(sourceType, targetType); + public INewInstanceMapping? Find(ITypeSymbol sourceType, ITypeSymbol targetType) => _mappings.Find(sourceType, targetType); - public ITypeMapping? Build(MappingBuilderContext ctx, bool resultIsReusable) + public INewInstanceMapping? Build(MappingBuilderContext ctx, bool resultIsReusable) { foreach (var mappingBuilder in _builders) { @@ -54,7 +54,7 @@ public MappingBuilder(MappingCollection mappings) if (resultIsReusable) { - _mappings.Add(mapping); + _mappings.AddNewInstanceMapping(mapping); } _mappings.EnqueueToBuildBody(mapping, ctx); diff --git a/src/Riok.Mapperly/Descriptors/MappingBuilders/MemoryMappingBuilder.cs b/src/Riok.Mapperly/Descriptors/MappingBuilders/MemoryMappingBuilder.cs index cdfae41f10..4e09837737 100644 --- a/src/Riok.Mapperly/Descriptors/MappingBuilders/MemoryMappingBuilder.cs +++ b/src/Riok.Mapperly/Descriptors/MappingBuilders/MemoryMappingBuilder.cs @@ -12,7 +12,7 @@ public static class MemoryMappingBuilder private const string SpanMemberName = nameof(Memory.Span); private const string ToArrayMethodName = nameof(Enumerable.ToArray); - public static TypeMapping? TryBuildMapping(MappingBuilderContext ctx) + public static NewInstanceMapping? TryBuildMapping(MappingBuilderContext ctx) { if (!ctx.IsConversionEnabled(MappingConversionType.Memory)) return null; @@ -104,7 +104,7 @@ public static class MemoryMappingBuilder return new SourceObjectMemberDelegateExistingTargetMapping(ctx.Source, ctx.Target, SpanMemberName, enumerableMapping); } - private static TypeMapping? BuildSpanToMemoryMapping(MappingBuilderContext ctx, ITypeMapping elementMapping) + private static NewInstanceMapping? BuildSpanToMemoryMapping(MappingBuilderContext ctx, INewInstanceMapping elementMapping) { if (elementMapping.IsSynthetic && !ctx.MapperConfiguration.UseDeepCloning) return new SourceObjectMethodMapping(ctx.Source, ctx.Target, ToArrayMethodName); @@ -115,7 +115,7 @@ public static class MemoryMappingBuilder : new CastMapping(ctx.Source, ctx.Target, arrayMapping); } - private static TypeMapping? BuildMemoryToArrayMapping(MappingBuilderContext ctx, ITypeMapping elementMapping) + private static NewInstanceMapping? BuildMemoryToArrayMapping(MappingBuilderContext ctx, INewInstanceMapping elementMapping) { if (!elementMapping.IsSynthetic || ctx.MapperConfiguration.UseDeepCloning) return BuildSpanToArrayMethodMapping(ctx, elementMapping); @@ -123,7 +123,7 @@ public static class MemoryMappingBuilder return new SourceObjectMethodMapping(ctx.Source, ctx.Target, ToArrayMethodName); } - private static TypeMapping? BuildMemoryToSpanMapping(MappingBuilderContext ctx, ITypeMapping elementMapping) + private static NewInstanceMapping? BuildMemoryToSpanMapping(MappingBuilderContext ctx, INewInstanceMapping elementMapping) { if (!elementMapping.IsSynthetic || ctx.MapperConfiguration.UseDeepCloning) return BuildMemoryToSpanMethod(ctx, elementMapping); @@ -131,7 +131,7 @@ public static class MemoryMappingBuilder return new SourceObjectMemberMapping(ctx.Source, ctx.Target, SpanMemberName); } - private static TypeMapping BuildArrayToMemoryMapping(MappingBuilderContext ctx, ITypeMapping elementMapping) + private static NewInstanceMapping BuildArrayToMemoryMapping(MappingBuilderContext ctx, INewInstanceMapping elementMapping) { if (!elementMapping.IsSynthetic || ctx.MapperConfiguration.UseDeepCloning) return new ArrayForMapping( @@ -144,7 +144,7 @@ private static TypeMapping BuildArrayToMemoryMapping(MappingBuilderContext ctx, return new CastMapping(ctx.Source, ctx.Target); } - private static TypeMapping? BuildMemoryToSpanMethod(MappingBuilderContext ctx, ITypeMapping elementMapping) + private static NewInstanceMapping? BuildMemoryToSpanMethod(MappingBuilderContext ctx, INewInstanceMapping elementMapping) { var sourceSpan = ctx.Types.Get(typeof(ReadOnlySpan<>)).Construct(elementMapping.SourceType); if (ctx.FindOrBuildMapping(sourceSpan, ctx.Target) is not { } spanMapping) @@ -153,7 +153,7 @@ private static TypeMapping BuildArrayToMemoryMapping(MappingBuilderContext ctx, return new SourceObjectMemberMapping(ctx.Source, ctx.Target, SpanMemberName, spanMapping); } - private static TypeMapping? BuildMemoryToMemoryMapping(MappingBuilderContext ctx, ITypeMapping elementMapping) + private static NewInstanceMapping? BuildMemoryToMemoryMapping(MappingBuilderContext ctx, INewInstanceMapping elementMapping) { if (!elementMapping.IsSynthetic || ctx.MapperConfiguration.UseDeepCloning) return BuildSpanToArrayMethodMapping(ctx, elementMapping); @@ -161,7 +161,7 @@ private static TypeMapping BuildArrayToMemoryMapping(MappingBuilderContext ctx, return new CastMapping(ctx.Source, ctx.Target); } - private static TypeMapping? BuildMemoryToEnumerableMapping(MappingBuilderContext ctx, ITypeMapping elementMapping) + private static NewInstanceMapping? BuildMemoryToEnumerableMapping(MappingBuilderContext ctx, INewInstanceMapping elementMapping) { var sourceSpan = ctx.Types.Get(typeof(ReadOnlySpan<>)).Construct(elementMapping.SourceType); if (ctx.FindOrBuildMapping(sourceSpan, ctx.Target) is not { } enumerableMapping) @@ -170,7 +170,7 @@ private static TypeMapping BuildArrayToMemoryMapping(MappingBuilderContext ctx, return new SourceObjectMemberMapping(ctx.Source, ctx.Target, SpanMemberName, enumerableMapping); } - private static TypeMapping? BuildEnumerableToMemoryMapping(MappingBuilderContext ctx, ITypeMapping elementMapping) + private static NewInstanceMapping? BuildEnumerableToMemoryMapping(MappingBuilderContext ctx, INewInstanceMapping elementMapping) { var targetArray = ctx.Types.GetArrayType(elementMapping.TargetType); if (ctx.FindOrBuildMapping(ctx.Source, targetArray.NonNullable()) is not { } arrayMapping) @@ -179,7 +179,7 @@ private static TypeMapping BuildArrayToMemoryMapping(MappingBuilderContext ctx, return new DelegateMapping(ctx.Source, ctx.Target, arrayMapping); } - private static TypeMapping? BuildSpanToArrayMethodMapping(MappingBuilderContext ctx, ITypeMapping elementMapping) + private static NewInstanceMapping? BuildSpanToArrayMethodMapping(MappingBuilderContext ctx, INewInstanceMapping elementMapping) { var sourceSpan = ctx.Types.Get(typeof(ReadOnlySpan<>)).Construct(elementMapping.SourceType); var targetArray = ctx.Types.GetArrayType(elementMapping.TargetType); diff --git a/src/Riok.Mapperly/Descriptors/MappingBuilders/NewInstanceObjectPropertyMappingBuilder.cs b/src/Riok.Mapperly/Descriptors/MappingBuilders/NewInstanceObjectPropertyMappingBuilder.cs index be84352298..432585b39f 100644 --- a/src/Riok.Mapperly/Descriptors/MappingBuilders/NewInstanceObjectPropertyMappingBuilder.cs +++ b/src/Riok.Mapperly/Descriptors/MappingBuilders/NewInstanceObjectPropertyMappingBuilder.cs @@ -8,7 +8,7 @@ namespace Riok.Mapperly.Descriptors.MappingBuilders; public static class NewInstanceObjectPropertyMappingBuilder { - public static TypeMapping? TryBuildMapping(MappingBuilderContext ctx) + public static NewInstanceMapping? TryBuildMapping(MappingBuilderContext ctx) { if (ctx.Target.SpecialType != SpecialType.None || ctx.Source.SpecialType != SpecialType.None) return null; diff --git a/src/Riok.Mapperly/Descriptors/MappingBuilders/NullableMappingBuilder.cs b/src/Riok.Mapperly/Descriptors/MappingBuilders/NullableMappingBuilder.cs index 1023351c54..6ff07a1acd 100644 --- a/src/Riok.Mapperly/Descriptors/MappingBuilders/NullableMappingBuilder.cs +++ b/src/Riok.Mapperly/Descriptors/MappingBuilders/NullableMappingBuilder.cs @@ -6,7 +6,7 @@ namespace Riok.Mapperly.Descriptors.MappingBuilders; public static class NullableMappingBuilder { - public static TypeMapping? TryBuildMapping(MappingBuilderContext ctx) + public static NewInstanceMapping? TryBuildMapping(MappingBuilderContext ctx) { var sourceIsNullable = ctx.Source.TryGetNonNullable(out var sourceNonNullable); var targetIsNullable = ctx.Target.TryGetNonNullable(out var targetNonNullable); @@ -32,7 +32,7 @@ public static class NullableMappingBuilder return delegateMapping == null ? null : new NullDelegateExistingTargetMapping(ctx.Source, ctx.Target, delegateMapping); } - private static TypeMapping BuildNullDelegateMapping(MappingBuilderContext ctx, ITypeMapping mapping) + private static NewInstanceMapping BuildNullDelegateMapping(MappingBuilderContext ctx, INewInstanceMapping mapping) { var nullFallback = ctx.GetNullFallbackValue(); return mapping switch diff --git a/src/Riok.Mapperly/Descriptors/MappingBuilders/QueryableMappingBuilder.cs b/src/Riok.Mapperly/Descriptors/MappingBuilders/QueryableMappingBuilder.cs index 526a3d9450..fd5d145825 100644 --- a/src/Riok.Mapperly/Descriptors/MappingBuilders/QueryableMappingBuilder.cs +++ b/src/Riok.Mapperly/Descriptors/MappingBuilders/QueryableMappingBuilder.cs @@ -7,7 +7,7 @@ namespace Riok.Mapperly.Descriptors.MappingBuilders; public static class QueryableMappingBuilder { - public static TypeMapping? TryBuildMapping(MappingBuilderContext ctx) + public static NewInstanceMapping? TryBuildMapping(MappingBuilderContext ctx) { if (!ctx.IsConversionEnabled(MappingConversionType.Queryable)) return null; diff --git a/src/Riok.Mapperly/Descriptors/MappingBuilders/SpanMappingBuilder.cs b/src/Riok.Mapperly/Descriptors/MappingBuilders/SpanMappingBuilder.cs index 3063768130..bbf9e84ca0 100644 --- a/src/Riok.Mapperly/Descriptors/MappingBuilders/SpanMappingBuilder.cs +++ b/src/Riok.Mapperly/Descriptors/MappingBuilders/SpanMappingBuilder.cs @@ -13,7 +13,7 @@ public static class SpanMappingBuilder private const string ToArrayMethodName = nameof(Enumerable.ToArray); private const string AddMethodName = nameof(ICollection.Add); - public static TypeMapping? TryBuildMapping(MappingBuilderContext ctx) + public static NewInstanceMapping? TryBuildMapping(MappingBuilderContext ctx) { if (!ctx.IsConversionEnabled(MappingConversionType.Span)) return null; @@ -115,7 +115,7 @@ ForEachAddEnumerableExistingTargetMapping CreateForEach(string methodName) } } - private static TypeMapping? BuildSpanToEnumerable(MappingBuilderContext ctx, ITypeMapping elementMapping) + private static NewInstanceMapping? BuildSpanToEnumerable(MappingBuilderContext ctx, INewInstanceMapping elementMapping) { var target = ctx.CollectionInfos!.Target; @@ -156,7 +156,7 @@ ExistingTargetMappingMethodWrapper CreateForEach(string methodName, ObjectFactor } } - private static TypeMapping BuildToArrayOrMap(MappingBuilderContext ctx, ITypeMapping elementMapping) + private static NewInstanceMapping BuildToArrayOrMap(MappingBuilderContext ctx, INewInstanceMapping elementMapping) { if (!elementMapping.IsSynthetic) return new ArrayForMapping(ctx.Source, ctx.Target, elementMapping, elementMapping.TargetType); @@ -164,7 +164,7 @@ private static TypeMapping BuildToArrayOrMap(MappingBuilderContext ctx, ITypeMap return new SourceObjectMethodMapping(ctx.Source, ctx.Target, ToArrayMethodName); } - private static TypeMapping? BuildEnumerableToSpan(MappingBuilderContext ctx, ITypeMapping elementMapping) + private static NewInstanceMapping? BuildEnumerableToSpan(MappingBuilderContext ctx, INewInstanceMapping elementMapping) { var typedArray = ctx.Types.GetArrayType(elementMapping.TargetType); if (ctx.FindOrBuildMapping(ctx.Source, typedArray) is not { } arrayMapping) @@ -173,7 +173,7 @@ private static TypeMapping BuildToArrayOrMap(MappingBuilderContext ctx, ITypeMap return new CastMapping(ctx.Source, ctx.Target, arrayMapping); } - private static TypeMapping? BuildSpanToList(MappingBuilderContext ctx, ITypeMapping elementMapping) + private static NewInstanceMapping? BuildSpanToList(MappingBuilderContext ctx, INewInstanceMapping elementMapping) { var typedList = ctx.Types.Get(typeof(List<>)).Construct(elementMapping.TargetType); if (ctx.FindOrBuildMapping(ctx.Source, typedList) is not { } listMapping) @@ -182,7 +182,7 @@ private static TypeMapping BuildToArrayOrMap(MappingBuilderContext ctx, ITypeMap return new DelegateMapping(ctx.Source, ctx.Target, listMapping); } - private static TypeMapping? MapSpanArrayToEnumerableMethod(MappingBuilderContext ctx) + private static NewInstanceMapping? MapSpanArrayToEnumerableMethod(MappingBuilderContext ctx) { var enumeratedType = ctx.CollectionInfos!.Source.EnumeratedType; var typedArray = ctx.Types.GetArrayType(enumeratedType); diff --git a/src/Riok.Mapperly/Descriptors/MappingBuilders/SpecialTypeMappingBuilder.cs b/src/Riok.Mapperly/Descriptors/MappingBuilders/SpecialTypeMappingBuilder.cs index cfb6325ee7..7ba6e0909a 100644 --- a/src/Riok.Mapperly/Descriptors/MappingBuilders/SpecialTypeMappingBuilder.cs +++ b/src/Riok.Mapperly/Descriptors/MappingBuilders/SpecialTypeMappingBuilder.cs @@ -7,7 +7,7 @@ namespace Riok.Mapperly.Descriptors.MappingBuilders; public static class SpecialTypeMappingBuilder { - public static TypeMapping? TryBuildMapping(MappingBuilderContext ctx) + public static NewInstanceMapping? TryBuildMapping(MappingBuilderContext ctx) { if (!ctx.IsConversionEnabled(MappingConversionType.ExplicitCast)) return null; diff --git a/src/Riok.Mapperly/Descriptors/MappingBuilders/StringToEnumMappingBuilder.cs b/src/Riok.Mapperly/Descriptors/MappingBuilders/StringToEnumMappingBuilder.cs index 77c9933468..9bed45a6c2 100644 --- a/src/Riok.Mapperly/Descriptors/MappingBuilders/StringToEnumMappingBuilder.cs +++ b/src/Riok.Mapperly/Descriptors/MappingBuilders/StringToEnumMappingBuilder.cs @@ -9,7 +9,7 @@ namespace Riok.Mapperly.Descriptors.MappingBuilders; public static class StringToEnumMappingBuilder { - public static TypeMapping? TryBuildMapping(MappingBuilderContext ctx) + public static NewInstanceMapping? TryBuildMapping(MappingBuilderContext ctx) { if (!ctx.IsConversionEnabled(MappingConversionType.StringToEnum)) return null; diff --git a/src/Riok.Mapperly/Descriptors/MappingBuilders/ToStringMappingBuilder.cs b/src/Riok.Mapperly/Descriptors/MappingBuilders/ToStringMappingBuilder.cs index eb18456086..1b1fc88a45 100644 --- a/src/Riok.Mapperly/Descriptors/MappingBuilders/ToStringMappingBuilder.cs +++ b/src/Riok.Mapperly/Descriptors/MappingBuilders/ToStringMappingBuilder.cs @@ -6,7 +6,7 @@ namespace Riok.Mapperly.Descriptors.MappingBuilders; public static class ToStringMappingBuilder { - public static TypeMapping? TryBuildMapping(MappingBuilderContext ctx) + public static NewInstanceMapping? TryBuildMapping(MappingBuilderContext ctx) { if (!ctx.IsConversionEnabled(MappingConversionType.ToStringMethod)) return null; diff --git a/src/Riok.Mapperly/Descriptors/MappingCollection.cs b/src/Riok.Mapperly/Descriptors/MappingCollection.cs index 50b67442e1..fe75557907 100644 --- a/src/Riok.Mapperly/Descriptors/MappingCollection.cs +++ b/src/Riok.Mapperly/Descriptors/MappingCollection.cs @@ -12,7 +12,7 @@ public class MappingCollection /// The first callable mapping of each type pair. /// Contains mappings to build and already built mappings /// - private readonly Dictionary _mappings = new(); + private readonly Dictionary _mappings = new(); /// /// A list of all method mappings (extra mappings and mappings) @@ -39,7 +39,7 @@ public class MappingCollection /// public IReadOnlyCollection UserMappings => _userMappings; - public ITypeMapping? Find(ITypeSymbol sourceType, ITypeSymbol targetType) + public INewInstanceMapping? Find(ITypeSymbol sourceType, ITypeSymbol targetType) { _mappings.TryGetValue(new TypeMappingKey(sourceType, targetType), out var mapping); return mapping; @@ -61,6 +61,21 @@ public void Add(ITypeMapping mapping) _userMappings.Add(userMapping); } + switch (mapping) + { + case INewInstanceMapping newInstanceMapping: + AddNewInstanceMapping(newInstanceMapping); + break; + case IExistingTargetMapping existingTargetMapping: + AddExistingTargetMapping(existingTargetMapping); + break; + default: + throw new ArgumentOutOfRangeException(nameof(mapping), mapping.GetType().FullName + " mappings are not supported"); + } + } + + public void AddNewInstanceMapping(INewInstanceMapping mapping) + { if (mapping is MethodMapping methodMapping) { _methodMappings.Add(methodMapping); @@ -72,8 +87,13 @@ public void Add(ITypeMapping mapping) } } - public void AddExistingTargetMapping(IExistingTargetMapping mapping) => - _existingTargetMappings.Add(new TypeMappingKey(mapping), mapping); + public void AddExistingTargetMapping(IExistingTargetMapping mapping) + { + if (mapping.CallableByOtherMappings && FindExistingInstanceMapping(mapping.SourceType, mapping.TargetType) is null) + { + _existingTargetMappings.Add(new TypeMappingKey(mapping), mapping); + } + } public IEnumerable<(IMapping, MappingBuilderContext)> DequeueMappingsToBuildBody() => _mappingsToBuildBody.DequeueAll(); } diff --git a/src/Riok.Mapperly/Descriptors/Mappings/ArrayCloneMapping.cs b/src/Riok.Mapperly/Descriptors/Mappings/ArrayCloneMapping.cs index b5270866ea..f48a25a7c2 100644 --- a/src/Riok.Mapperly/Descriptors/Mappings/ArrayCloneMapping.cs +++ b/src/Riok.Mapperly/Descriptors/Mappings/ArrayCloneMapping.cs @@ -9,7 +9,7 @@ namespace Riok.Mapperly.Descriptors.Mappings; /// /// Represents a mapping from an array to an array of the same type by using Array.Clone. /// -public class ArrayCloneMapping : TypeMapping +public class ArrayCloneMapping : NewInstanceMapping { private const string CloneMethodName = nameof(Array.Clone); diff --git a/src/Riok.Mapperly/Descriptors/Mappings/ArrayForMapping.cs b/src/Riok.Mapperly/Descriptors/Mappings/ArrayForMapping.cs index 866b13d512..ca32a67f8c 100644 --- a/src/Riok.Mapperly/Descriptors/Mappings/ArrayForMapping.cs +++ b/src/Riok.Mapperly/Descriptors/Mappings/ArrayForMapping.cs @@ -11,10 +11,15 @@ public class ArrayForMapping : MethodMapping private const string LoopCounterName = "i"; private const string ArrayLengthProperty = nameof(Array.Length); - private readonly ITypeMapping _elementMapping; + private readonly INewInstanceMapping _elementMapping; private readonly ITypeSymbol _targetArrayElementType; - public ArrayForMapping(ITypeSymbol sourceType, ITypeSymbol targetType, ITypeMapping elementMapping, ITypeSymbol targetArrayElementType) + public ArrayForMapping( + ITypeSymbol sourceType, + ITypeSymbol targetType, + INewInstanceMapping elementMapping, + ITypeSymbol targetArrayElementType + ) : base(sourceType, targetType) { _elementMapping = elementMapping; diff --git a/src/Riok.Mapperly/Descriptors/Mappings/CastMapping.cs b/src/Riok.Mapperly/Descriptors/Mappings/CastMapping.cs index 313bb282c1..5c51e5e658 100644 --- a/src/Riok.Mapperly/Descriptors/Mappings/CastMapping.cs +++ b/src/Riok.Mapperly/Descriptors/Mappings/CastMapping.cs @@ -8,11 +8,11 @@ namespace Riok.Mapperly.Descriptors.Mappings; /// /// Represents a cast mapping. /// -public class CastMapping : TypeMapping +public class CastMapping : NewInstanceMapping { - private readonly ITypeMapping? _delegateMapping; + private readonly INewInstanceMapping? _delegateMapping; - public CastMapping(ITypeSymbol sourceType, ITypeSymbol targetType, ITypeMapping? delegateMapping = null) + public CastMapping(ITypeSymbol sourceType, ITypeSymbol targetType, INewInstanceMapping? delegateMapping = null) : base(sourceType, targetType) { _delegateMapping = delegateMapping; diff --git a/src/Riok.Mapperly/Descriptors/Mappings/CtorMapping.cs b/src/Riok.Mapperly/Descriptors/Mappings/CtorMapping.cs index 0ca578dbc7..3a697fb429 100644 --- a/src/Riok.Mapperly/Descriptors/Mappings/CtorMapping.cs +++ b/src/Riok.Mapperly/Descriptors/Mappings/CtorMapping.cs @@ -8,7 +8,7 @@ namespace Riok.Mapperly.Descriptors.Mappings; /// /// Represents a mapping where the target type has the source as single ctor argument. /// -public class CtorMapping : TypeMapping +public class CtorMapping : NewInstanceMapping { public CtorMapping(ITypeSymbol sourceType, ITypeSymbol targetType) : base(sourceType, targetType) { } diff --git a/src/Riok.Mapperly/Descriptors/Mappings/DelegateMapping.cs b/src/Riok.Mapperly/Descriptors/Mappings/DelegateMapping.cs index 48f44f257b..eacc70f76c 100644 --- a/src/Riok.Mapperly/Descriptors/Mappings/DelegateMapping.cs +++ b/src/Riok.Mapperly/Descriptors/Mappings/DelegateMapping.cs @@ -4,16 +4,16 @@ namespace Riok.Mapperly.Descriptors.Mappings; /// -/// Represents a mapping generated from invoking on a source value. +/// Represents a mapping generated from invoking on a source value. /// /// target = Map(source); /// /// -public class DelegateMapping : TypeMapping +public class DelegateMapping : NewInstanceMapping { - private readonly ITypeMapping _delegateMapping; + private readonly INewInstanceMapping _delegateMapping; - public DelegateMapping(ITypeSymbol sourceType, ITypeSymbol targetType, ITypeMapping delegateMapping) + public DelegateMapping(ITypeSymbol sourceType, ITypeSymbol targetType, INewInstanceMapping delegateMapping) : base(sourceType, targetType) { _delegateMapping = delegateMapping; diff --git a/src/Riok.Mapperly/Descriptors/Mappings/DerivedTypeIfExpressionMapping.cs b/src/Riok.Mapperly/Descriptors/Mappings/DerivedTypeIfExpressionMapping.cs index c5f22244a4..8ebd156ced 100644 --- a/src/Riok.Mapperly/Descriptors/Mappings/DerivedTypeIfExpressionMapping.cs +++ b/src/Riok.Mapperly/Descriptors/Mappings/DerivedTypeIfExpressionMapping.cs @@ -10,11 +10,15 @@ namespace Riok.Mapperly.Descriptors.Mappings; /// A derived type mapping maps one base type or interface to another /// by implementing a if with instance checks over known types and performs the provided mapping for each type. /// -public class DerivedTypeIfExpressionMapping : TypeMapping +public class DerivedTypeIfExpressionMapping : NewInstanceMapping { - private readonly IReadOnlyCollection _typeMappings; + private readonly IReadOnlyCollection _typeMappings; - public DerivedTypeIfExpressionMapping(ITypeSymbol sourceType, ITypeSymbol targetType, IReadOnlyCollection typeMappings) + public DerivedTypeIfExpressionMapping( + ITypeSymbol sourceType, + ITypeSymbol targetType, + IReadOnlyCollection typeMappings + ) : base(sourceType, targetType) { _typeMappings = typeMappings; @@ -25,14 +29,21 @@ public override ExpressionSyntax Build(TypeMappingBuildContext ctx) // source is A x ? MapToA(x) : var typeExpressions = _typeMappings .Reverse() - .Aggregate(DefaultLiteral(), (aggregate, current) => BuildConditional(ctx, aggregate, current)); + .Aggregate( + DefaultLiteral(), + (aggregate, current) => BuildConditional(ctx, aggregate, current) + ); // cast to target type, to ensure the compiler picks the correct type // (B)( return CastExpression(FullyQualifiedIdentifier(TargetType), ParenthesizedExpression(typeExpressions)); } - private ConditionalExpressionSyntax BuildConditional(TypeMappingBuildContext ctx, ExpressionSyntax notMatched, ITypeMapping mapping) + private ConditionalExpressionSyntax BuildConditional( + TypeMappingBuildContext ctx, + ExpressionSyntax notMatched, + INewInstanceMapping mapping + ) { // cannot use is pattern matching is operator due to expression limitations // use is with a cast instead diff --git a/src/Riok.Mapperly/Descriptors/Mappings/DerivedTypeSwitchMapping.cs b/src/Riok.Mapperly/Descriptors/Mappings/DerivedTypeSwitchMapping.cs index 0cd033495f..f70103f3bc 100644 --- a/src/Riok.Mapperly/Descriptors/Mappings/DerivedTypeSwitchMapping.cs +++ b/src/Riok.Mapperly/Descriptors/Mappings/DerivedTypeSwitchMapping.cs @@ -9,13 +9,13 @@ namespace Riok.Mapperly.Descriptors.Mappings; /// A derived type mapping maps one base type or interface to another /// by implementing a type switch over known types and performs the provided mapping for each type. /// -public class DerivedTypeSwitchMapping : TypeMapping +public class DerivedTypeSwitchMapping : NewInstanceMapping { private const string GetTypeMethodName = nameof(GetType); - private readonly IReadOnlyCollection _typeMappings; + private readonly IReadOnlyCollection _typeMappings; - public DerivedTypeSwitchMapping(ITypeSymbol sourceType, ITypeSymbol targetType, IReadOnlyCollection typeMappings) + public DerivedTypeSwitchMapping(ITypeSymbol sourceType, ITypeSymbol targetType, IReadOnlyCollection typeMappings) : base(sourceType, targetType) { _typeMappings = typeMappings; diff --git a/src/Riok.Mapperly/Descriptors/Mappings/DirectAssignmentMapping.cs b/src/Riok.Mapperly/Descriptors/Mappings/DirectAssignmentMapping.cs index e7f2fe6062..d628563250 100644 --- a/src/Riok.Mapperly/Descriptors/Mappings/DirectAssignmentMapping.cs +++ b/src/Riok.Mapperly/Descriptors/Mappings/DirectAssignmentMapping.cs @@ -7,7 +7,7 @@ namespace Riok.Mapperly.Descriptors.Mappings; /// Represents a direct assignment mapping. /// Source and target types need to be the same types. /// -public class DirectAssignmentMapping : TypeMapping +public class DirectAssignmentMapping : NewInstanceMapping { public DirectAssignmentMapping(ITypeSymbol type) : base(type, type) { } diff --git a/src/Riok.Mapperly/Descriptors/Mappings/Enums/EnumFallbackValueMapping.cs b/src/Riok.Mapperly/Descriptors/Mappings/Enums/EnumFallbackValueMapping.cs index ff8b801927..3f45dd77cc 100644 --- a/src/Riok.Mapperly/Descriptors/Mappings/Enums/EnumFallbackValueMapping.cs +++ b/src/Riok.Mapperly/Descriptors/Mappings/Enums/EnumFallbackValueMapping.cs @@ -9,14 +9,14 @@ namespace Riok.Mapperly.Descriptors.Mappings.Enums; /// Enum fallback value which is used if no enum value matched. /// Either throws or returns the fallback value. /// -public class EnumFallbackValueMapping : TypeMapping +public class EnumFallbackValueMapping : NewInstanceMapping { - private readonly ITypeMapping? _fallbackMapping; + private readonly INewInstanceMapping? _fallbackMapping; public EnumFallbackValueMapping( ITypeSymbol source, ITypeSymbol target, - ITypeMapping? fallbackMapping = null, + INewInstanceMapping? fallbackMapping = null, IFieldSymbol? fallbackMember = null ) : base(source, target) diff --git a/src/Riok.Mapperly/Descriptors/Mappings/Enums/EnumFromStringParseMapping.cs b/src/Riok.Mapperly/Descriptors/Mappings/Enums/EnumFromStringParseMapping.cs index 849f466dd5..fd8b0fd08c 100644 --- a/src/Riok.Mapperly/Descriptors/Mappings/Enums/EnumFromStringParseMapping.cs +++ b/src/Riok.Mapperly/Descriptors/Mappings/Enums/EnumFromStringParseMapping.cs @@ -11,7 +11,7 @@ namespace Riok.Mapperly.Descriptors.Mappings.Enums; /// Less efficient than /// but works in . /// -public class EnumFromStringParseMapping : TypeMapping +public class EnumFromStringParseMapping : NewInstanceMapping { private const string EnumClassName = "System.Enum"; private const string ParseMethodName = "Parse"; diff --git a/src/Riok.Mapperly/Descriptors/Mappings/ExistingTarget/ExistingTargetMapping.cs b/src/Riok.Mapperly/Descriptors/Mappings/ExistingTarget/ExistingTargetMapping.cs index 286f2975ca..6446f67d68 100644 --- a/src/Riok.Mapperly/Descriptors/Mappings/ExistingTarget/ExistingTargetMapping.cs +++ b/src/Riok.Mapperly/Descriptors/Mappings/ExistingTarget/ExistingTargetMapping.cs @@ -18,6 +18,10 @@ protected ExistingTargetMapping(ITypeSymbol sourceType, ITypeSymbol targetType) public ITypeSymbol TargetType { get; } + public virtual bool CallableByOtherMappings => true; + + public virtual bool IsSynthetic => false; + public MappingBodyBuildingPriority BodyBuildingPriority => MappingBodyBuildingPriority.Default; public abstract IEnumerable Build(TypeMappingBuildContext ctx, ExpressionSyntax target); diff --git a/src/Riok.Mapperly/Descriptors/Mappings/ExistingTarget/ForEachAddEnumerableExistingTargetMapping.cs b/src/Riok.Mapperly/Descriptors/Mappings/ExistingTarget/ForEachAddEnumerableExistingTargetMapping.cs index 1d97d1829d..c65d4d0dba 100644 --- a/src/Riok.Mapperly/Descriptors/Mappings/ExistingTarget/ForEachAddEnumerableExistingTargetMapping.cs +++ b/src/Riok.Mapperly/Descriptors/Mappings/ExistingTarget/ForEachAddEnumerableExistingTargetMapping.cs @@ -14,14 +14,14 @@ public class ForEachAddEnumerableExistingTargetMapping : ExistingTargetMapping { private const string LoopItemVariableName = "item"; - private readonly ITypeMapping _elementMapping; + private readonly INewInstanceMapping _elementMapping; private readonly string _insertMethodName; private readonly EnsureCapacityInfo? _ensureCapacityBuilder; public ForEachAddEnumerableExistingTargetMapping( ITypeSymbol sourceType, ITypeSymbol targetType, - ITypeMapping elementMapping, + INewInstanceMapping elementMapping, string insertMethodName, EnsureCapacityInfo? ensureCapacityBuilder ) diff --git a/src/Riok.Mapperly/Descriptors/Mappings/ExistingTarget/ForEachSetDictionaryExistingTargetMapping.cs b/src/Riok.Mapperly/Descriptors/Mappings/ExistingTarget/ForEachSetDictionaryExistingTargetMapping.cs index 980640a388..67a12129bf 100644 --- a/src/Riok.Mapperly/Descriptors/Mappings/ExistingTarget/ForEachSetDictionaryExistingTargetMapping.cs +++ b/src/Riok.Mapperly/Descriptors/Mappings/ExistingTarget/ForEachSetDictionaryExistingTargetMapping.cs @@ -17,16 +17,16 @@ public class ForEachSetDictionaryExistingTargetMapping : ExistingTargetMapping private const string KeyPropertyName = nameof(KeyValuePair.Key); private const string ValuePropertyName = nameof(KeyValuePair.Value); - private readonly ITypeMapping _keyMapping; - private readonly ITypeMapping _valueMapping; + private readonly INewInstanceMapping _keyMapping; + private readonly INewInstanceMapping _valueMapping; private readonly INamedTypeSymbol? _explicitCast; private readonly EnsureCapacityInfo? _ensureCapacity; public ForEachSetDictionaryExistingTargetMapping( ITypeSymbol sourceType, ITypeSymbol targetType, - ITypeMapping keyMapping, - ITypeMapping valueMapping, + INewInstanceMapping keyMapping, + INewInstanceMapping valueMapping, INamedTypeSymbol? explicitCast, EnsureCapacityInfo? ensureCapacity ) diff --git a/src/Riok.Mapperly/Descriptors/Mappings/ExistingTarget/IExistingTargetMapping.cs b/src/Riok.Mapperly/Descriptors/Mappings/ExistingTarget/IExistingTargetMapping.cs index e57780e9ac..936b9c69e1 100644 --- a/src/Riok.Mapperly/Descriptors/Mappings/ExistingTarget/IExistingTargetMapping.cs +++ b/src/Riok.Mapperly/Descriptors/Mappings/ExistingTarget/IExistingTargetMapping.cs @@ -5,7 +5,13 @@ namespace Riok.Mapperly.Descriptors.Mappings.ExistingTarget; /// /// A mapping which can be applied to an existing target type object instance. /// -public interface IExistingTargetMapping : IMapping +public interface IExistingTargetMapping : ITypeMapping { + /// + /// Serializes the existing target mapping as c# syntax. + /// + /// The build context. + /// The target of the existing target mapping. + /// The built syntax. IEnumerable Build(TypeMappingBuildContext ctx, ExpressionSyntax target); } diff --git a/src/Riok.Mapperly/Descriptors/Mappings/ExistingTarget/ObjectMemberExistingTargetMapping.cs b/src/Riok.Mapperly/Descriptors/Mappings/ExistingTarget/ObjectMemberExistingTargetMapping.cs index 8225bcfc29..072ea33bf0 100644 --- a/src/Riok.Mapperly/Descriptors/Mappings/ExistingTarget/ObjectMemberExistingTargetMapping.cs +++ b/src/Riok.Mapperly/Descriptors/Mappings/ExistingTarget/ObjectMemberExistingTargetMapping.cs @@ -19,5 +19,9 @@ public ObjectMemberExistingTargetMapping(ITypeSymbol sourceType, ITypeSymbol tar public ITypeSymbol TargetType { get; } + public bool CallableByOtherMappings => true; + + public bool IsSynthetic => false; + public MappingBodyBuildingPriority BodyBuildingPriority => MappingBodyBuildingPriority.Default; } diff --git a/src/Riok.Mapperly/Descriptors/Mappings/ForEachAddEnumerableMapping.cs b/src/Riok.Mapperly/Descriptors/Mappings/ForEachAddEnumerableMapping.cs index 972e99fa63..8003560d59 100644 --- a/src/Riok.Mapperly/Descriptors/Mappings/ForEachAddEnumerableMapping.cs +++ b/src/Riok.Mapperly/Descriptors/Mappings/ForEachAddEnumerableMapping.cs @@ -18,7 +18,7 @@ public class ForEachAddEnumerableMapping : ExistingTargetMappingMethodWrapper public ForEachAddEnumerableMapping( ITypeSymbol sourceType, ITypeSymbol targetType, - ITypeMapping elementMapping, + INewInstanceMapping elementMapping, ObjectFactory? objectFactory, string insertMethodName, EnsureCapacityInfo? ensureCapacityBuilder diff --git a/src/Riok.Mapperly/Descriptors/Mappings/ForEachSetDictionaryMapping.cs b/src/Riok.Mapperly/Descriptors/Mappings/ForEachSetDictionaryMapping.cs index 1056899351..439cbdf06c 100644 --- a/src/Riok.Mapperly/Descriptors/Mappings/ForEachSetDictionaryMapping.cs +++ b/src/Riok.Mapperly/Descriptors/Mappings/ForEachSetDictionaryMapping.cs @@ -22,8 +22,8 @@ public class ForEachSetDictionaryMapping : ExistingTargetMappingMethodWrapper public ForEachSetDictionaryMapping( ITypeSymbol sourceType, ITypeSymbol targetType, - ITypeMapping keyMapping, - ITypeMapping valueMapping, + INewInstanceMapping keyMapping, + INewInstanceMapping valueMapping, bool sourceHasCount, ITypeSymbol? typeToInstantiate = null, ObjectFactory? objectFactory = null, diff --git a/src/Riok.Mapperly/Descriptors/Mappings/INewInstanceMapping.cs b/src/Riok.Mapperly/Descriptors/Mappings/INewInstanceMapping.cs new file mode 100644 index 0000000000..4ca930752e --- /dev/null +++ b/src/Riok.Mapperly/Descriptors/Mappings/INewInstanceMapping.cs @@ -0,0 +1,16 @@ +using Microsoft.CodeAnalysis.CSharp.Syntax; + +namespace Riok.Mapperly.Descriptors.Mappings; + +/// +/// Represents a mapping from one type to another new instance. +/// +public interface INewInstanceMapping : ITypeMapping +{ + /// + /// Serializes the mapping as c# syntax. + /// + /// The build context. + /// The built syntax. + ExpressionSyntax Build(TypeMappingBuildContext ctx); +} diff --git a/src/Riok.Mapperly/Descriptors/Mappings/ITypeMapping.cs b/src/Riok.Mapperly/Descriptors/Mappings/ITypeMapping.cs index 60c397e3cb..8840cec063 100644 --- a/src/Riok.Mapperly/Descriptors/Mappings/ITypeMapping.cs +++ b/src/Riok.Mapperly/Descriptors/Mappings/ITypeMapping.cs @@ -1,10 +1,7 @@ -using Microsoft.CodeAnalysis.CSharp.Syntax; - -namespace Riok.Mapperly.Descriptors.Mappings; +namespace Riok.Mapperly.Descriptors.Mappings; /// /// Represents a mapping from one type to another. -/// The target is usually a new instance. /// public interface ITypeMapping : IMapping { @@ -18,11 +15,4 @@ public interface ITypeMapping : IMapping /// Gets a value indicating whether this mapping produces any code or can be omitted completely (eg. direct assignments or delegate mappings). /// bool IsSynthetic { get; } - - /// - /// Serializes the mapping as c# syntax. - /// - /// The build context. - /// The built syntax. - ExpressionSyntax Build(TypeMappingBuildContext ctx); } diff --git a/src/Riok.Mapperly/Descriptors/Mappings/LinqConstructorMapping.cs b/src/Riok.Mapperly/Descriptors/Mappings/LinqConstructorMapping.cs index 8bb49ab350..4c48fe7109 100644 --- a/src/Riok.Mapperly/Descriptors/Mappings/LinqConstructorMapping.cs +++ b/src/Riok.Mapperly/Descriptors/Mappings/LinqConstructorMapping.cs @@ -8,17 +8,17 @@ namespace Riok.Mapperly.Descriptors.Mappings; /// /// Represents an enumerable mapping where the target type accepts IEnumerable as a single argument. /// -public class LinqConstructorMapping : TypeMapping +public class LinqConstructorMapping : NewInstanceMapping { private readonly INamedTypeSymbol _targetTypeToConstruct; - private readonly ITypeMapping _elementMapping; + private readonly INewInstanceMapping _elementMapping; private readonly string? _selectMethod; public LinqConstructorMapping( ITypeSymbol sourceType, ITypeSymbol targetType, INamedTypeSymbol targetTypeToConstruct, - ITypeMapping elementMapping, + INewInstanceMapping elementMapping, string? selectMethod ) : base(sourceType, targetType) diff --git a/src/Riok.Mapperly/Descriptors/Mappings/LinqDictionaryMapping.cs b/src/Riok.Mapperly/Descriptors/Mappings/LinqDictionaryMapping.cs index 1ab9d4ea2b..f410d9e2de 100644 --- a/src/Riok.Mapperly/Descriptors/Mappings/LinqDictionaryMapping.cs +++ b/src/Riok.Mapperly/Descriptors/Mappings/LinqDictionaryMapping.cs @@ -8,21 +8,21 @@ namespace Riok.Mapperly.Descriptors.Mappings; /// /// Represents an enumerable mapping which works by using linq (select + collect). /// -public class LinqDictionaryMapping : TypeMapping +public class LinqDictionaryMapping : NewInstanceMapping { private const string KeyPropertyName = nameof(KeyValuePair.Key); private const string ValuePropertyName = nameof(KeyValuePair.Value); private readonly string _collectMethod; - private readonly ITypeMapping _keyMapping; - private readonly ITypeMapping _valueMapping; + private readonly INewInstanceMapping _keyMapping; + private readonly INewInstanceMapping _valueMapping; public LinqDictionaryMapping( ITypeSymbol sourceType, ITypeSymbol targetType, string collectMethod, - ITypeMapping keyMapping, - ITypeMapping valueMapping + INewInstanceMapping keyMapping, + INewInstanceMapping valueMapping ) : base(sourceType, targetType) { diff --git a/src/Riok.Mapperly/Descriptors/Mappings/LinqEnumerableMapping.cs b/src/Riok.Mapperly/Descriptors/Mappings/LinqEnumerableMapping.cs index 2a97e33456..03cae41eb6 100644 --- a/src/Riok.Mapperly/Descriptors/Mappings/LinqEnumerableMapping.cs +++ b/src/Riok.Mapperly/Descriptors/Mappings/LinqEnumerableMapping.cs @@ -8,16 +8,16 @@ namespace Riok.Mapperly.Descriptors.Mappings; /// /// Represents an enumerable mapping which works by using linq (select + collect). /// -public class LinqEnumerableMapping : TypeMapping +public class LinqEnumerableMapping : NewInstanceMapping { - private readonly ITypeMapping _elementMapping; + private readonly INewInstanceMapping _elementMapping; private readonly string? _selectMethod; private readonly string? _collectMethod; public LinqEnumerableMapping( ITypeSymbol sourceType, ITypeSymbol targetType, - ITypeMapping elementMapping, + INewInstanceMapping elementMapping, string? selectMethod, string? collectMethod ) diff --git a/src/Riok.Mapperly/Descriptors/Mappings/MemberMappings/MemberMapping.cs b/src/Riok.Mapperly/Descriptors/Mappings/MemberMappings/MemberMapping.cs index f7fc73a957..4c37f1594c 100644 --- a/src/Riok.Mapperly/Descriptors/Mappings/MemberMappings/MemberMapping.cs +++ b/src/Riok.Mapperly/Descriptors/Mappings/MemberMappings/MemberMapping.cs @@ -9,11 +9,16 @@ namespace Riok.Mapperly.Descriptors.Mappings.MemberMappings; /// public class MemberMapping : IMemberMapping { - private readonly ITypeMapping _delegateMapping; + private readonly INewInstanceMapping _delegateMapping; private readonly bool _nullConditionalAccess; private readonly bool _addValuePropertyOnNullable; - public MemberMapping(ITypeMapping delegateMapping, MemberPath sourcePath, bool nullConditionalAccess, bool addValuePropertyOnNullable) + public MemberMapping( + INewInstanceMapping delegateMapping, + MemberPath sourcePath, + bool nullConditionalAccess, + bool addValuePropertyOnNullable + ) { _delegateMapping = delegateMapping; SourcePath = sourcePath; diff --git a/src/Riok.Mapperly/Descriptors/Mappings/MemberMappings/NullMemberMapping.cs b/src/Riok.Mapperly/Descriptors/Mappings/MemberMappings/NullMemberMapping.cs index f6d67fc417..48f9ce0bb3 100644 --- a/src/Riok.Mapperly/Descriptors/Mappings/MemberMappings/NullMemberMapping.cs +++ b/src/Riok.Mapperly/Descriptors/Mappings/MemberMappings/NullMemberMapping.cs @@ -15,13 +15,13 @@ namespace Riok.Mapperly.Descriptors.Mappings.MemberMappings; [DebuggerDisplay("NullMemberMapping({SourcePath}: {_delegateMapping})")] public class NullMemberMapping : IMemberMapping { - private readonly ITypeMapping _delegateMapping; + private readonly INewInstanceMapping _delegateMapping; private readonly ITypeSymbol _targetType; private readonly NullFallbackValue _nullFallback; private readonly bool _useNullConditionalAccess; public NullMemberMapping( - ITypeMapping delegateMapping, + INewInstanceMapping delegateMapping, MemberPath sourcePath, ITypeSymbol targetType, NullFallbackValue nullFallback, diff --git a/src/Riok.Mapperly/Descriptors/Mappings/MethodMapping.cs b/src/Riok.Mapperly/Descriptors/Mappings/MethodMapping.cs index a5852717cc..5bf8920cf6 100644 --- a/src/Riok.Mapperly/Descriptors/Mappings/MethodMapping.cs +++ b/src/Riok.Mapperly/Descriptors/Mappings/MethodMapping.cs @@ -13,7 +13,7 @@ namespace Riok.Mapperly.Descriptors.Mappings; /// /// Represents a mapping which is not a single expression but an entire method. /// -public abstract class MethodMapping : TypeMapping +public abstract class MethodMapping : NewInstanceMapping { protected const string DefaultReferenceHandlerParameterName = "refHandler"; private const string DefaultSourceParameterName = "source"; diff --git a/src/Riok.Mapperly/Descriptors/Mappings/TypeMapping.cs b/src/Riok.Mapperly/Descriptors/Mappings/NewInstanceMapping.cs similarity index 67% rename from src/Riok.Mapperly/Descriptors/Mappings/TypeMapping.cs rename to src/Riok.Mapperly/Descriptors/Mappings/NewInstanceMapping.cs index 76dfa03ba4..3968fc0f23 100644 --- a/src/Riok.Mapperly/Descriptors/Mappings/TypeMapping.cs +++ b/src/Riok.Mapperly/Descriptors/Mappings/NewInstanceMapping.cs @@ -4,11 +4,11 @@ namespace Riok.Mapperly.Descriptors.Mappings; -/// +/// [DebuggerDisplay("{GetType().Name}({SourceType} => {TargetType})")] -public abstract class TypeMapping : ITypeMapping +public abstract class NewInstanceMapping : INewInstanceMapping { - protected TypeMapping(ITypeSymbol sourceType, ITypeSymbol targetType) + protected NewInstanceMapping(ITypeSymbol sourceType, ITypeSymbol targetType) { SourceType = sourceType; TargetType = targetType; @@ -20,10 +20,10 @@ protected TypeMapping(ITypeSymbol sourceType, ITypeSymbol targetType) public virtual MappingBodyBuildingPriority BodyBuildingPriority => MappingBodyBuildingPriority.Default; - /// + /// public virtual bool CallableByOtherMappings => true; - /// + /// public virtual bool IsSynthetic => false; public abstract ExpressionSyntax Build(TypeMappingBuildContext ctx); diff --git a/src/Riok.Mapperly/Descriptors/Mappings/NewInstanceObjectMemberMapping.cs b/src/Riok.Mapperly/Descriptors/Mappings/NewInstanceObjectMemberMapping.cs index 11f2c5e930..c6954af5d5 100644 --- a/src/Riok.Mapperly/Descriptors/Mappings/NewInstanceObjectMemberMapping.cs +++ b/src/Riok.Mapperly/Descriptors/Mappings/NewInstanceObjectMemberMapping.cs @@ -10,7 +10,7 @@ namespace Riok.Mapperly.Descriptors.Mappings; /// mapping properties via ctor, object initializer but not by assigning. /// /// -public class NewInstanceObjectMemberMapping : TypeMapping, INewInstanceObjectMemberMapping +public class NewInstanceObjectMemberMapping : NewInstanceMapping, INewInstanceObjectMemberMapping { private readonly HashSet _constructorPropertyMappings = new(); private readonly HashSet _initPropertyMappings = new(); diff --git a/src/Riok.Mapperly/Descriptors/Mappings/NewValueTupleConstructorMapping.cs b/src/Riok.Mapperly/Descriptors/Mappings/NewValueTupleConstructorMapping.cs index ee01fdd11e..79142d2ea5 100644 --- a/src/Riok.Mapperly/Descriptors/Mappings/NewValueTupleConstructorMapping.cs +++ b/src/Riok.Mapperly/Descriptors/Mappings/NewValueTupleConstructorMapping.cs @@ -11,7 +11,7 @@ namespace Riok.Mapperly.Descriptors.Mappings; /// mapping properties via ctor, but not by assigning. /// /// -public class NewValueTupleConstructorMapping : TypeMapping, INewValueTupleMapping +public class NewValueTupleConstructorMapping : NewInstanceMapping, INewValueTupleMapping { private const string ValueTupleName = "global::System.ValueTuple"; private readonly HashSet _constructorPropertyMappings = new(); diff --git a/src/Riok.Mapperly/Descriptors/Mappings/NullDelegateMapping.cs b/src/Riok.Mapperly/Descriptors/Mappings/NullDelegateMapping.cs index 622180bfb2..033e856374 100644 --- a/src/Riok.Mapperly/Descriptors/Mappings/NullDelegateMapping.cs +++ b/src/Riok.Mapperly/Descriptors/Mappings/NullDelegateMapping.cs @@ -10,17 +10,17 @@ namespace Riok.Mapperly.Descriptors.Mappings; /// /// Null aware delegate mapping. Abstracts handling null values of the delegated mapping. /// -public class NullDelegateMapping : TypeMapping +public class NullDelegateMapping : NewInstanceMapping { private const string NullableValueProperty = nameof(Nullable.Value); - private readonly ITypeMapping _delegateMapping; + private readonly INewInstanceMapping _delegateMapping; private readonly NullFallbackValue _nullFallbackValue; public NullDelegateMapping( ITypeSymbol nullableSourceType, ITypeSymbol nullableTargetType, - ITypeMapping delegateMapping, + INewInstanceMapping delegateMapping, NullFallbackValue nullFallbackValue ) : base(nullableSourceType, nullableTargetType) diff --git a/src/Riok.Mapperly/Descriptors/Mappings/QueryableProjectionMapping.cs b/src/Riok.Mapperly/Descriptors/Mappings/QueryableProjectionMapping.cs index eec9f7870b..c50c2b17b8 100644 --- a/src/Riok.Mapperly/Descriptors/Mappings/QueryableProjectionMapping.cs +++ b/src/Riok.Mapperly/Descriptors/Mappings/QueryableProjectionMapping.cs @@ -14,9 +14,9 @@ public class QueryableProjectionMapping : MethodMapping private const string QueryableReceiverName = "System.Linq.Queryable"; private const string SelectMethodName = nameof(Queryable.Select); - private readonly ITypeMapping _delegateMapping; + private readonly INewInstanceMapping _delegateMapping; - public QueryableProjectionMapping(ITypeSymbol sourceType, ITypeSymbol targetType, ITypeMapping delegateMapping) + public QueryableProjectionMapping(ITypeSymbol sourceType, ITypeSymbol targetType, INewInstanceMapping delegateMapping) : base(sourceType, targetType) { _delegateMapping = delegateMapping; diff --git a/src/Riok.Mapperly/Descriptors/Mappings/SourceObjectMemberMapping.cs b/src/Riok.Mapperly/Descriptors/Mappings/SourceObjectMemberMapping.cs index a061a677d2..5615fc3e76 100644 --- a/src/Riok.Mapperly/Descriptors/Mappings/SourceObjectMemberMapping.cs +++ b/src/Riok.Mapperly/Descriptors/Mappings/SourceObjectMemberMapping.cs @@ -12,16 +12,16 @@ namespace Riok.Mapperly.Descriptors.Mappings; /// target = Map(source.Span); /// /// -public class SourceObjectMemberMapping : TypeMapping +public class SourceObjectMemberMapping : NewInstanceMapping { private readonly string _memberName; - private readonly ITypeMapping? _delegateMapping; + private readonly INewInstanceMapping? _delegateMapping; public SourceObjectMemberMapping( ITypeSymbol sourceType, ITypeSymbol targetType, string memberName, - ITypeMapping? delegateMapping = null + INewInstanceMapping? delegateMapping = null ) : base(sourceType, targetType) { diff --git a/src/Riok.Mapperly/Descriptors/Mappings/SourceObjectMethodMapping.cs b/src/Riok.Mapperly/Descriptors/Mappings/SourceObjectMethodMapping.cs index ad3012d17a..5a2b27652d 100644 --- a/src/Riok.Mapperly/Descriptors/Mappings/SourceObjectMethodMapping.cs +++ b/src/Riok.Mapperly/Descriptors/Mappings/SourceObjectMethodMapping.cs @@ -13,16 +13,16 @@ namespace Riok.Mapperly.Descriptors.Mappings; /// target = Map(source.ToArray()); /// /// -public class SourceObjectMethodMapping : TypeMapping +public class SourceObjectMethodMapping : NewInstanceMapping { private readonly string _methodName; - private readonly ITypeMapping? _delegateMapping; + private readonly INewInstanceMapping? _delegateMapping; public SourceObjectMethodMapping( ITypeSymbol sourceType, ITypeSymbol targetType, string methodName, - ITypeMapping? delegateMapping = null + INewInstanceMapping? delegateMapping = null ) : base(sourceType, targetType) { diff --git a/src/Riok.Mapperly/Descriptors/Mappings/StaticMethodMapping.cs b/src/Riok.Mapperly/Descriptors/Mappings/StaticMethodMapping.cs index fa6ca63b36..2d88bfb38c 100644 --- a/src/Riok.Mapperly/Descriptors/Mappings/StaticMethodMapping.cs +++ b/src/Riok.Mapperly/Descriptors/Mappings/StaticMethodMapping.cs @@ -7,7 +7,7 @@ namespace Riok.Mapperly.Descriptors.Mappings; /// /// Represents a mapping which works by invoking a static method with the source as only argument. /// -public class StaticMethodMapping : TypeMapping +public class StaticMethodMapping : NewInstanceMapping { private readonly IMethodSymbol _method; diff --git a/src/Riok.Mapperly/Descriptors/Mappings/UserMappings/IDelegateUserMapping.cs b/src/Riok.Mapperly/Descriptors/Mappings/UserMappings/IDelegateUserMapping.cs index 91b5ab5b56..7fe53e337b 100644 --- a/src/Riok.Mapperly/Descriptors/Mappings/UserMappings/IDelegateUserMapping.cs +++ b/src/Riok.Mapperly/Descriptors/Mappings/UserMappings/IDelegateUserMapping.cs @@ -8,11 +8,11 @@ public interface IDelegateUserMapping : IUserMapping /// /// Gets the delegate mapping or null if none is set (yet). /// - ITypeMapping? DelegateMapping { get; } + INewInstanceMapping? DelegateMapping { get; } /// /// Sets the delegate mapping. /// /// The mapping. - void SetDelegateMapping(ITypeMapping mapping); + void SetDelegateMapping(INewInstanceMapping mapping); } diff --git a/src/Riok.Mapperly/Descriptors/Mappings/UserMappings/UserDefinedNewInstanceMethodMapping.cs b/src/Riok.Mapperly/Descriptors/Mappings/UserMappings/UserDefinedNewInstanceMethodMapping.cs index 05dd177b44..145bcba175 100644 --- a/src/Riok.Mapperly/Descriptors/Mappings/UserMappings/UserDefinedNewInstanceMethodMapping.cs +++ b/src/Riok.Mapperly/Descriptors/Mappings/UserMappings/UserDefinedNewInstanceMethodMapping.cs @@ -32,9 +32,9 @@ bool enableReferenceHandling public IMethodSymbol Method { get; } - public ITypeMapping? DelegateMapping { get; private set; } + public INewInstanceMapping? DelegateMapping { get; private set; } - public void SetDelegateMapping(ITypeMapping mapping) => DelegateMapping = mapping; + public void SetDelegateMapping(INewInstanceMapping mapping) => DelegateMapping = mapping; public override IEnumerable BuildBody(TypeMappingBuildContext ctx) { diff --git a/src/Riok.Mapperly/Descriptors/Mappings/UserMappings/UserImplementedExistingTargetMethodMapping.cs b/src/Riok.Mapperly/Descriptors/Mappings/UserMappings/UserImplementedExistingTargetMethodMapping.cs new file mode 100644 index 0000000000..5d57e6644d --- /dev/null +++ b/src/Riok.Mapperly/Descriptors/Mappings/UserMappings/UserImplementedExistingTargetMethodMapping.cs @@ -0,0 +1,72 @@ +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Riok.Mapperly.Descriptors.Mappings.ExistingTarget; +using Riok.Mapperly.Emit; +using Riok.Mapperly.Helpers; +using Riok.Mapperly.Symbols; + +namespace Riok.Mapperly.Descriptors.Mappings.UserMappings; + +/// +/// Represents an existing target type mapper which is implemented by the user. +/// +public class UserImplementedExistingTargetMethodMapping : ExistingTargetMapping, IUserMapping +{ + private readonly MethodParameter _sourceParameter; + private readonly MethodParameter _targetParameter; + private readonly MethodParameter? _referenceHandlerParameter; + + public UserImplementedExistingTargetMethodMapping( + IMethodSymbol method, + MethodParameter sourceParameter, + MethodParameter targetParameter, + MethodParameter? referenceHandlerParameter + ) + : base(method.Parameters[0].Type.UpgradeNullable(), targetParameter.Type.UpgradeNullable()) + { + Method = method; + _sourceParameter = sourceParameter; + _targetParameter = targetParameter; + _referenceHandlerParameter = referenceHandlerParameter; + } + + public IMethodSymbol Method { get; } + + public ExpressionSyntax Build(TypeMappingBuildContext ctx) => + throw new InvalidOperationException( + $"{nameof(UserImplementedExistingTargetMethodMapping)} {ctx.Source}, {ctx.ReferenceHandler} does not support {nameof(Build)}" + ); + + public override IEnumerable Build(TypeMappingBuildContext ctx, ExpressionSyntax target) + { + // if the user implemented method is on an interface, + // we explicitly cast to be able to use the default interface implementation or explicit implementations + if (Method.ReceiverType?.TypeKind != TypeKind.Interface) + { + yield return SyntaxFactory.ExpressionStatement( + SyntaxFactoryHelper.Invocation( + Method.Name, + _sourceParameter.WithArgument(ctx.Source), + _targetParameter.WithArgument(target), + _referenceHandlerParameter?.WithArgument(ctx.ReferenceHandler) + ) + ); + yield break; + } + + var castedThis = SyntaxFactory.CastExpression( + SyntaxFactoryHelper.FullyQualifiedIdentifier(Method.ReceiverType!), + SyntaxFactory.ThisExpression() + ); + var method = SyntaxFactoryHelper.MemberAccess(SyntaxFactory.ParenthesizedExpression(castedThis), Method.Name); + yield return SyntaxFactory.ExpressionStatement( + SyntaxFactoryHelper.Invocation( + method, + _sourceParameter.WithArgument(ctx.Source), + _targetParameter.WithArgument(target), + _referenceHandlerParameter?.WithArgument(ctx.ReferenceHandler) + ) + ); + } +} diff --git a/src/Riok.Mapperly/Descriptors/Mappings/UserMappings/UserImplementedMethodMapping.cs b/src/Riok.Mapperly/Descriptors/Mappings/UserMappings/UserImplementedMethodMapping.cs index 5f40bb39f8..c600fb45f8 100644 --- a/src/Riok.Mapperly/Descriptors/Mappings/UserMappings/UserImplementedMethodMapping.cs +++ b/src/Riok.Mapperly/Descriptors/Mappings/UserMappings/UserImplementedMethodMapping.cs @@ -10,7 +10,7 @@ namespace Riok.Mapperly.Descriptors.Mappings.UserMappings; /// /// Represents a mapping method on the mapper which is implemented by the user. /// -public class UserImplementedMethodMapping : TypeMapping, IUserMapping +public class UserImplementedMethodMapping : NewInstanceMapping, IUserMapping { private readonly MethodParameter _sourceParameter; private readonly MethodParameter? _referenceHandlerParameter; diff --git a/src/Riok.Mapperly/Descriptors/TypeMappingKey.cs b/src/Riok.Mapperly/Descriptors/TypeMappingKey.cs index 860f630e36..7aea2396f4 100644 --- a/src/Riok.Mapperly/Descriptors/TypeMappingKey.cs +++ b/src/Riok.Mapperly/Descriptors/TypeMappingKey.cs @@ -1,6 +1,5 @@ using Microsoft.CodeAnalysis; using Riok.Mapperly.Descriptors.Mappings; -using Riok.Mapperly.Descriptors.Mappings.ExistingTarget; using Riok.Mapperly.Helpers; namespace Riok.Mapperly.Descriptors; @@ -14,9 +13,6 @@ public readonly struct TypeMappingKey public TypeMappingKey(ITypeMapping mapping, bool includeNullability = true) : this(mapping.SourceType, mapping.TargetType, includeNullability) { } - public TypeMappingKey(IExistingTargetMapping mapping, bool includeNullability = true) - : this(mapping.SourceType, mapping.TargetType, includeNullability) { } - public TypeMappingKey(ITypeSymbol source, ITypeSymbol target, bool includeNullability = true) { _source = includeNullability ? source : source.NonNullable(); diff --git a/src/Riok.Mapperly/Descriptors/UserMethodMappingExtractor.cs b/src/Riok.Mapperly/Descriptors/UserMethodMappingExtractor.cs index 549a766a76..f48f1501fe 100644 --- a/src/Riok.Mapperly/Descriptors/UserMethodMappingExtractor.cs +++ b/src/Riok.Mapperly/Descriptors/UserMethodMappingExtractor.cs @@ -66,13 +66,21 @@ private static IEnumerable ExtractBaseMethods(SimpleMappingBuilde bool isStatic ) { - var valid = - method is { ReturnsVoid: false, IsGenericMethod: false } - && (allowPartial || !method.IsPartialDefinition) - && (!isStatic || method.IsStatic); - return valid && BuildParameters(ctx, method, out var parameters) - ? new UserImplementedMethodMapping(method, parameters.Source, parameters.ReferenceHandler) - : null; + var valid = !method.IsGenericMethod && (allowPartial || !method.IsPartialDefinition) && (!isStatic || method.IsStatic); + + if (!valid || !BuildParameters(ctx, method, out var parameters)) + { + return null; + } + + return method.ReturnsVoid + ? new UserImplementedExistingTargetMethodMapping( + method, + parameters.Source, + parameters.Target!.Value, + parameters.ReferenceHandler + ) + : new UserImplementedMethodMapping(method, parameters.Source, parameters.ReferenceHandler); } private static IUserMapping? BuilderUserDefinedMapping(SimpleMappingBuilderContext ctx, IMethodSymbol methodSymbol, bool isStatic) diff --git a/src/Riok.Mapperly/Emit/ReferenceHandlingSyntaxFactoryHelper.cs b/src/Riok.Mapperly/Emit/ReferenceHandlingSyntaxFactoryHelper.cs index 0f573c5bee..fa1ad114d7 100644 --- a/src/Riok.Mapperly/Emit/ReferenceHandlingSyntaxFactoryHelper.cs +++ b/src/Riok.Mapperly/Emit/ReferenceHandlingSyntaxFactoryHelper.cs @@ -11,7 +11,7 @@ public static class ReferenceHandlingSyntaxFactoryHelper { private const string ExistingTargetVariableName = "existingTargetReference"; - public static IfStatementSyntax TryGetReference(ITypeMapping mapping, TypeMappingBuildContext ctx) + public static IfStatementSyntax TryGetReference(INewInstanceMapping mapping, TypeMappingBuildContext ctx) { // GetReference var refHandler = ctx.ReferenceHandler ?? throw new ArgumentException("Reference handler is not set", nameof(ctx)); @@ -35,7 +35,7 @@ public static IfStatementSyntax TryGetReference(ITypeMapping mapping, TypeMappin return IfStatement(invocation, ReturnStatement(IdentifierName(ExistingTargetVariableName))); } - public static ExpressionSyntax SetReference(ITypeMapping mapping, TypeMappingBuildContext ctx, ExpressionSyntax target) + public static ExpressionSyntax SetReference(INewInstanceMapping mapping, TypeMappingBuildContext ctx, ExpressionSyntax target) { // SetReference var refHandler = ctx.ReferenceHandler ?? throw new ArgumentException("Reference handler is not set", nameof(ctx)); diff --git a/src/Riok.Mapperly/Symbols/RuntimeTargetTypeMapping.cs b/src/Riok.Mapperly/Symbols/RuntimeTargetTypeMapping.cs index a73167fecf..281cfa8a58 100644 --- a/src/Riok.Mapperly/Symbols/RuntimeTargetTypeMapping.cs +++ b/src/Riok.Mapperly/Symbols/RuntimeTargetTypeMapping.cs @@ -2,4 +2,4 @@ namespace Riok.Mapperly.Symbols; -public record RuntimeTargetTypeMapping(ITypeMapping Mapping, bool IsAssignableToMethodTargetType); +public record RuntimeTargetTypeMapping(INewInstanceMapping Mapping, bool IsAssignableToMethodTargetType); diff --git a/test/Riok.Mapperly.IntegrationTests/BaseMapperTest.cs b/test/Riok.Mapperly.IntegrationTests/BaseMapperTest.cs index a769805480..50e285afe6 100644 --- a/test/Riok.Mapperly.IntegrationTests/BaseMapperTest.cs +++ b/test/Riok.Mapperly.IntegrationTests/BaseMapperTest.cs @@ -110,6 +110,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 37c189a0fa..6ce3d979e8 100644 --- a/test/Riok.Mapperly.IntegrationTests/Dto/TestObjectDto.cs +++ b/test/Riok.Mapperly.IntegrationTests/Dto/TestObjectDto.cs @@ -81,9 +81,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 83994b372c..3af649863d 100644 --- a/test/Riok.Mapperly.IntegrationTests/Mapper/StaticTestMapper.cs +++ b/test/Riok.Mapperly.IntegrationTests/Mapper/StaticTestMapper.cs @@ -39,6 +39,14 @@ public static TestObjectDto MapToDto(TestObject src) return target; } + public static void MapExistingList(List src, List dst) + { + foreach (var item in src) + { + dst.Add(int.Parse(item)); + } + } + [MapProperty(nameof(TestObject.RenamedStringValue), nameof(TestObjectDto.RenamedStringValue2))] [MapProperty( new[] { nameof(TestObject.UnflatteningIdValue) }, diff --git a/test/Riok.Mapperly.IntegrationTests/Models/TestObject.cs b/test/Riok.Mapperly.IntegrationTests/Models/TestObject.cs index 9d69eda85f..f2a273ba73 100644 --- a/test/Riok.Mapperly.IntegrationTests/Models/TestObject.cs +++ b/test/Riok.Mapperly.IntegrationTests/Models/TestObject.cs @@ -79,9 +79,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/DeepCloningMapperTest.RunMappingShouldWork.verified.txt b/test/Riok.Mapperly.IntegrationTests/_snapshots/NET_48/DeepCloningMapperTest.RunMappingShouldWork.verified.txt index 699a80182d..64c8ef0c0e 100644 --- a/test/Riok.Mapperly.IntegrationTests/_snapshots/NET_48/DeepCloningMapperTest.RunMappingShouldWork.verified.txt +++ b/test/Riok.Mapperly.IntegrationTests/_snapshots/NET_48/DeepCloningMapperTest.RunMappingShouldWork.verified.txt @@ -128,6 +128,11 @@ 2, 3 ], + ExistingList: [ + 1, + 2, + 3 + ], ISet: [ 1, 2, diff --git a/test/Riok.Mapperly.IntegrationTests/_snapshots/NET_48/DeepCloningMapperTest.SnapshotGeneratedSource.verified.cs b/test/Riok.Mapperly.IntegrationTests/_snapshots/NET_48/DeepCloningMapperTest.SnapshotGeneratedSource.verified.cs index 5d8fccb952..b880f3d0a3 100644 --- a/test/Riok.Mapperly.IntegrationTests/_snapshots/NET_48/DeepCloningMapperTest.SnapshotGeneratedSource.verified.cs +++ b/test/Riok.Mapperly.IntegrationTests/_snapshots/NET_48/DeepCloningMapperTest.SnapshotGeneratedSource.verified.cs @@ -90,6 +90,11 @@ public static partial class DeepCloningMapper target.ExistingSortedSet.Add(item2); } + foreach (var item3 in src.ExistingList) + { + target.ExistingList.Add(item3); + } + target.ISet = global::System.Linq.Enumerable.ToHashSet(src.ISet); target.HashSet = global::System.Linq.Enumerable.ToHashSet(src.HashSet); target.SortedSet = new global::System.Collections.Generic.SortedSet(src.SortedSet); 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 a24ad94486..377d513745 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 @@ -144,6 +144,11 @@ 2, 3 ], + ExistingList: [ + 1, + 2, + 3 + ], ISet: [ 1, 2, diff --git a/test/Riok.Mapperly.IntegrationTests/_snapshots/NET_48/MapperTest.SnapshotGeneratedSource.verified.cs b/test/Riok.Mapperly.IntegrationTests/_snapshots/NET_48/MapperTest.SnapshotGeneratedSource.verified.cs index f0c7137d39..9a08e4ef14 100644 --- a/test/Riok.Mapperly.IntegrationTests/_snapshots/NET_48/MapperTest.SnapshotGeneratedSource.verified.cs +++ b/test/Riok.Mapperly.IntegrationTests/_snapshots/NET_48/MapperTest.SnapshotGeneratedSource.verified.cs @@ -131,6 +131,11 @@ public partial int ParseableInt(string value) target.ExistingSortedSet.Add(ParseableInt(item2)); } + 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.HashSet = global::System.Linq.Enumerable.ToHashSet(global::System.Linq.Enumerable.Select(testObject.HashSet, x => ParseableInt(x))); target.SortedSet = new global::System.Collections.Generic.SortedSet(global::System.Linq.Enumerable.Select(testObject.SortedSet, x => ParseableInt(x))); @@ -214,6 +219,11 @@ public partial int ParseableInt(string value) target.ExistingSortedSet.Add(item2.ToString()); } + 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.HashSet = global::System.Linq.Enumerable.ToHashSet(global::System.Linq.Enumerable.Select(dto.HashSet, x => x.ToString())); target.SortedSet = new global::System.Collections.Generic.SortedSet(global::System.Linq.Enumerable.Select(dto.SortedSet, x => x.ToString())); @@ -302,6 +312,11 @@ public partial void UpdateDto(global::Riok.Mapperly.IntegrationTests.Models.Test target.ExistingSortedSet.Add(ParseableInt(item2)); } + 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.HashSet = global::System.Linq.Enumerable.ToHashSet(global::System.Linq.Enumerable.Select(source.HashSet, x => ParseableInt(x))); target.SortedSet = new global::System.Collections.Generic.SortedSet(global::System.Linq.Enumerable.Select(source.SortedSet, x => ParseableInt(x))); diff --git a/test/Riok.Mapperly.IntegrationTests/_snapshots/NET_48/StaticMapperTest.RunExtensionMappingShouldWork.verified.txt b/test/Riok.Mapperly.IntegrationTests/_snapshots/NET_48/StaticMapperTest.RunExtensionMappingShouldWork.verified.txt index a5818925d2..461ef9856d 100644 --- a/test/Riok.Mapperly.IntegrationTests/_snapshots/NET_48/StaticMapperTest.RunExtensionMappingShouldWork.verified.txt +++ b/test/Riok.Mapperly.IntegrationTests/_snapshots/NET_48/StaticMapperTest.RunExtensionMappingShouldWork.verified.txt @@ -139,6 +139,11 @@ 2, 3 ], + ExistingList: [ + 1, + 2, + 3 + ], ISet: [ 1, 2, diff --git a/test/Riok.Mapperly.IntegrationTests/_snapshots/NET_48/StaticMapperTest.RunMappingShouldWork.verified.txt b/test/Riok.Mapperly.IntegrationTests/_snapshots/NET_48/StaticMapperTest.RunMappingShouldWork.verified.txt index 13dfd1453a..42ed5b8902 100644 --- a/test/Riok.Mapperly.IntegrationTests/_snapshots/NET_48/StaticMapperTest.RunMappingShouldWork.verified.txt +++ b/test/Riok.Mapperly.IntegrationTests/_snapshots/NET_48/StaticMapperTest.RunMappingShouldWork.verified.txt @@ -144,6 +144,11 @@ 2, 3 ], + ExistingList: [ + 1, + 2, + 3 + ], ISet: [ 1, 2, diff --git a/test/Riok.Mapperly.IntegrationTests/_snapshots/NET_48/StaticMapperTest.SnapshotGeneratedSource.verified.cs b/test/Riok.Mapperly.IntegrationTests/_snapshots/NET_48/StaticMapperTest.SnapshotGeneratedSource.verified.cs index 420014428d..4bfb6544f7 100644 --- a/test/Riok.Mapperly.IntegrationTests/_snapshots/NET_48/StaticMapperTest.SnapshotGeneratedSource.verified.cs +++ b/test/Riok.Mapperly.IntegrationTests/_snapshots/NET_48/StaticMapperTest.SnapshotGeneratedSource.verified.cs @@ -128,6 +128,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.HashSet = global::System.Linq.Enumerable.ToHashSet(global::System.Linq.Enumerable.Select(src.HashSet, x => ParseableInt(x))); target.SortedSet = new global::System.Collections.Generic.SortedSet(global::System.Linq.Enumerable.Select(src.SortedSet, x => ParseableInt(x))); @@ -229,6 +230,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.HashSet = global::System.Linq.Enumerable.ToHashSet(global::System.Linq.Enumerable.Select(testObject.HashSet, x => ParseableInt(x))); target.SortedSet = new global::System.Collections.Generic.SortedSet(global::System.Linq.Enumerable.Select(testObject.SortedSet, x => ParseableInt(x))); @@ -312,6 +314,11 @@ public static partial int ParseableInt(string value) target.ExistingSortedSet.Add(item2.ToString()); } + 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.HashSet = global::System.Linq.Enumerable.ToHashSet(global::System.Linq.Enumerable.Select(dto.HashSet, x => x.ToString())); target.SortedSet = new global::System.Collections.Generic.SortedSet(global::System.Linq.Enumerable.Select(dto.SortedSet, x => x.ToString())); @@ -400,6 +407,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.HashSet = global::System.Linq.Enumerable.ToHashSet(global::System.Linq.Enumerable.Select(source.HashSet, x => ParseableInt(x))); target.SortedSet = new global::System.Collections.Generic.SortedSet(global::System.Linq.Enumerable.Select(source.SortedSet, x => ParseableInt(x))); diff --git a/test/Riok.Mapperly.IntegrationTests/_snapshots/Roslyn_4_4_OR_LOWER/DeepCloningMapperTest.RunMappingShouldWork.verified.txt b/test/Riok.Mapperly.IntegrationTests/_snapshots/Roslyn_4_4_OR_LOWER/DeepCloningMapperTest.RunMappingShouldWork.verified.txt index 6fa816fe88..56481798b4 100644 --- a/test/Riok.Mapperly.IntegrationTests/_snapshots/Roslyn_4_4_OR_LOWER/DeepCloningMapperTest.RunMappingShouldWork.verified.txt +++ b/test/Riok.Mapperly.IntegrationTests/_snapshots/Roslyn_4_4_OR_LOWER/DeepCloningMapperTest.RunMappingShouldWork.verified.txt @@ -128,6 +128,11 @@ 2, 3 ], + ExistingList: [ + 1, + 2, + 3 + ], ISet: [ 1, 2, diff --git a/test/Riok.Mapperly.IntegrationTests/_snapshots/Roslyn_4_4_OR_LOWER/DeepCloningMapperTest.SnapshotGeneratedSource.verified.cs b/test/Riok.Mapperly.IntegrationTests/_snapshots/Roslyn_4_4_OR_LOWER/DeepCloningMapperTest.SnapshotGeneratedSource.verified.cs index 31702ce6af..dae4625a15 100644 --- a/test/Riok.Mapperly.IntegrationTests/_snapshots/Roslyn_4_4_OR_LOWER/DeepCloningMapperTest.SnapshotGeneratedSource.verified.cs +++ b/test/Riok.Mapperly.IntegrationTests/_snapshots/Roslyn_4_4_OR_LOWER/DeepCloningMapperTest.SnapshotGeneratedSource.verified.cs @@ -88,6 +88,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_4_OR_LOWER/MapperTest.RunMappingShouldWork.verified.txt b/test/Riok.Mapperly.IntegrationTests/_snapshots/Roslyn_4_4_OR_LOWER/MapperTest.RunMappingShouldWork.verified.txt index 9c57b7ac72..6b5f6eda63 100644 --- a/test/Riok.Mapperly.IntegrationTests/_snapshots/Roslyn_4_4_OR_LOWER/MapperTest.RunMappingShouldWork.verified.txt +++ b/test/Riok.Mapperly.IntegrationTests/_snapshots/Roslyn_4_4_OR_LOWER/MapperTest.RunMappingShouldWork.verified.txt @@ -144,6 +144,11 @@ 2, 3 ], + ExistingList: [ + 1, + 2, + 3 + ], ISet: [ 1, 2, diff --git a/test/Riok.Mapperly.IntegrationTests/_snapshots/Roslyn_4_4_OR_LOWER/MapperTest.SnapshotGeneratedSource.verified.cs b/test/Riok.Mapperly.IntegrationTests/_snapshots/Roslyn_4_4_OR_LOWER/MapperTest.SnapshotGeneratedSource.verified.cs index ddf9e83691..8cc08d7bd0 100644 --- a/test/Riok.Mapperly.IntegrationTests/_snapshots/Roslyn_4_4_OR_LOWER/MapperTest.SnapshotGeneratedSource.verified.cs +++ b/test/Riok.Mapperly.IntegrationTests/_snapshots/Roslyn_4_4_OR_LOWER/MapperTest.SnapshotGeneratedSource.verified.cs @@ -129,6 +129,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())); @@ -301,6 +313,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))); diff --git a/test/Riok.Mapperly.IntegrationTests/_snapshots/Roslyn_4_4_OR_LOWER/StaticMapperTest.RunExtensionMappingShouldWork.verified.txt b/test/Riok.Mapperly.IntegrationTests/_snapshots/Roslyn_4_4_OR_LOWER/StaticMapperTest.RunExtensionMappingShouldWork.verified.txt index 3437d7e928..0ef8572b04 100644 --- a/test/Riok.Mapperly.IntegrationTests/_snapshots/Roslyn_4_4_OR_LOWER/StaticMapperTest.RunExtensionMappingShouldWork.verified.txt +++ b/test/Riok.Mapperly.IntegrationTests/_snapshots/Roslyn_4_4_OR_LOWER/StaticMapperTest.RunExtensionMappingShouldWork.verified.txt @@ -139,6 +139,11 @@ 2, 3 ], + ExistingList: [ + 1, + 2, + 3 + ], ISet: [ 1, 2, diff --git a/test/Riok.Mapperly.IntegrationTests/_snapshots/Roslyn_4_4_OR_LOWER/StaticMapperTest.RunMappingShouldWork.verified.txt b/test/Riok.Mapperly.IntegrationTests/_snapshots/Roslyn_4_4_OR_LOWER/StaticMapperTest.RunMappingShouldWork.verified.txt index 06c3a7cec3..7adc77cebd 100644 --- a/test/Riok.Mapperly.IntegrationTests/_snapshots/Roslyn_4_4_OR_LOWER/StaticMapperTest.RunMappingShouldWork.verified.txt +++ b/test/Riok.Mapperly.IntegrationTests/_snapshots/Roslyn_4_4_OR_LOWER/StaticMapperTest.RunMappingShouldWork.verified.txt @@ -144,6 +144,11 @@ 2, 3 ], + ExistingList: [ + 1, + 2, + 3 + ], ISet: [ 1, 2, diff --git a/test/Riok.Mapperly.IntegrationTests/_snapshots/Roslyn_4_4_OR_LOWER/StaticMapperTest.SnapshotGeneratedSource.verified.cs b/test/Riok.Mapperly.IntegrationTests/_snapshots/Roslyn_4_4_OR_LOWER/StaticMapperTest.SnapshotGeneratedSource.verified.cs index 561c950218..69334be403 100644 --- a/test/Riok.Mapperly.IntegrationTests/_snapshots/Roslyn_4_4_OR_LOWER/StaticMapperTest.SnapshotGeneratedSource.verified.cs +++ b/test/Riok.Mapperly.IntegrationTests/_snapshots/Roslyn_4_4_OR_LOWER/StaticMapperTest.SnapshotGeneratedSource.verified.cs @@ -126,6 +126,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))); @@ -226,6 +227,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))); @@ -308,6 +310,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())); @@ -398,6 +406,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))); 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 6fa816fe88..56481798b4 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 @@ -128,6 +128,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 e01ee96c3f..8757eeeec7 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 @@ -91,6 +91,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 9c57b7ac72..6b5f6eda63 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 @@ -144,6 +144,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 866db20596..46c11b6cf6 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 @@ -132,6 +132,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))); @@ -217,6 +223,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())); @@ -307,6 +319,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))); 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 3437d7e928..0ef8572b04 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 @@ -139,6 +139,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 06c3a7cec3..7adc77cebd 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 @@ -144,6 +144,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 ecda47bce6..0a1d08b2d4 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 @@ -129,6 +129,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))); @@ -232,6 +233,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))); @@ -317,6 +319,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())); @@ -407,6 +415,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))); diff --git a/test/Riok.Mapperly.Tests/Mapping/UserMethodTest.cs b/test/Riok.Mapperly.Tests/Mapping/UserMethodTest.cs index 4474c7c8c7..f2fef9e530 100644 --- a/test/Riok.Mapperly.Tests/Mapping/UserMethodTest.cs +++ b/test/Riok.Mapperly.Tests/Mapping/UserMethodTest.cs @@ -55,6 +55,18 @@ public record B(int Value); return TestHelper.VerifyGenerator(source); } + [Fact] + public Task InstanceMapperShouldUseStaticExistingTargetMethod() + { + var source = TestSourceBuilder.MapperWithBodyAndTypes( + "partial B Map(A s);" + "static void StaticMapper(List src, List dst) { }", + "class A { public List Value { get; set; } }", + "public class B { public List Value { get; } }" + ); + + return TestHelper.VerifyGenerator(source); + } + [Fact] public void WithMultipleUserImplementedMethodShouldWork() { @@ -289,6 +301,48 @@ class B { public string Value { get; set; } public long Value2 { get; set; } pub return TestHelper.VerifyGenerator(source); } + [Fact] + public Task ExistingTargetsWithClassBaseTypeShouldWork() + { + var source = TestSourceBuilder.CSharp( + """ + using System; + using System.Collections.Generic; + using Riok.Mapperly.Abstractions; + + [Mapper] + public partial class BaseMapper : BaseMapper3 + { + public void MyMapping(List src, List dst) { } + + protected partial void MyIntToShortMapping(List src, List dst); + } + + public interface BaseMapper2 : BaseMapper3 + { + void MyMapping2(int src, long dst); + } + + public interface BaseMapper3 + { + void MyMapping3(C src, D dst) { } + } + + [Mapper] + public partial class MyMapper : BaseMapper, BaseMapper2 + { + public partial B Map(A source); + } + + class A { public List Value { get; set; } public int Value2 { get; set; } public C Value3 { get; set; } public List Value4 { get; set; } } + class B { public List Value { get; } public long Value2 { get; } public D Value3 { get; } public List Value4 { get; } }, + class C { public int Value { get; set; } }, + class D { public string Value { get; set; } }, + """ + ); + return TestHelper.VerifyGenerator(source); + } + [Fact] public Task WithMapperClassModifiersShouldCopyModifiersToMapper() { diff --git a/test/Riok.Mapperly.Tests/_snapshots/UserMethodTest.ExistingTargetsWithClassBaseTypeShouldWork#BaseMapper.g.verified.cs b/test/Riok.Mapperly.Tests/_snapshots/UserMethodTest.ExistingTargetsWithClassBaseTypeShouldWork#BaseMapper.g.verified.cs new file mode 100644 index 0000000000..4c2cdc3c50 --- /dev/null +++ b/test/Riok.Mapperly.Tests/_snapshots/UserMethodTest.ExistingTargetsWithClassBaseTypeShouldWork#BaseMapper.g.verified.cs @@ -0,0 +1,14 @@ +//HintName: BaseMapper.g.cs +// +#nullable enable +public partial class BaseMapper +{ + protected partial void MyIntToShortMapping(global::System.Collections.Generic.List src, global::System.Collections.Generic.List dst) + { + dst.EnsureCapacity(src.Count + dst.Count); + foreach (var item in src) + { + dst.Add((short)item); + } + } +} diff --git a/test/Riok.Mapperly.Tests/_snapshots/UserMethodTest.ExistingTargetsWithClassBaseTypeShouldWork#MyMapper.g.verified.cs b/test/Riok.Mapperly.Tests/_snapshots/UserMethodTest.ExistingTargetsWithClassBaseTypeShouldWork#MyMapper.g.verified.cs new file mode 100644 index 0000000000..1f5510f802 --- /dev/null +++ b/test/Riok.Mapperly.Tests/_snapshots/UserMethodTest.ExistingTargetsWithClassBaseTypeShouldWork#MyMapper.g.verified.cs @@ -0,0 +1,15 @@ +//HintName: MyMapper.g.cs +// +#nullable enable +public partial class MyMapper +{ + public partial global::B Map(global::A source) + { + var target = new global::B(); + MyMapping(source.Value, target.Value); + ((global::BaseMapper2)this).MyMapping2(source.Value2, target.Value2); + ((global::BaseMapper3)this).MyMapping3(source.Value3, target.Value3); + MyIntToShortMapping(source.Value4, target.Value4); + return target; + } +} diff --git a/test/Riok.Mapperly.Tests/_snapshots/UserMethodTest.InstanceMapperShouldUseStaticExistingTargetMethod#Mapper.g.verified.cs b/test/Riok.Mapperly.Tests/_snapshots/UserMethodTest.InstanceMapperShouldUseStaticExistingTargetMethod#Mapper.g.verified.cs new file mode 100644 index 0000000000..37b82dce36 --- /dev/null +++ b/test/Riok.Mapperly.Tests/_snapshots/UserMethodTest.InstanceMapperShouldUseStaticExistingTargetMethod#Mapper.g.verified.cs @@ -0,0 +1,12 @@ +//HintName: Mapper.g.cs +// +#nullable enable +public partial class Mapper +{ + private partial global::B Map(global::A s) + { + var target = new global::B(); + StaticMapper(s.Value, target.Value); + return target; + } +} \ No newline at end of file