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
- 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